Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
7b21bd4
feat(picker-column): add styles, disabled and active states
liamdebeasi Dec 1, 2023
9d0834b
chore(): add updated snapshots
Ionitron Dec 1, 2023
1aeb194
chore: run build
liamdebeasi Dec 1, 2023
eace642
refactor: add slot to integrate basic options
liamdebeasi Dec 1, 2023
b68c93d
refactor: scrolling column sets value
liamdebeasi Dec 1, 2023
2f3f9dc
refactor: clicking option sets value
liamdebeasi Dec 1, 2023
75ee951
chore: lint
liamdebeasi Dec 1, 2023
b1fc672
fix: column scrolls into view when option is ready
liamdebeasi Dec 1, 2023
2c773ed
fix: do not emit ionChange if value did not change
liamdebeasi Dec 1, 2023
3470c64
build and lint
liamdebeasi Dec 1, 2023
8d5a043
add api
liamdebeasi Dec 1, 2023
34ec94f
test: picker-column tests pass
liamdebeasi Dec 1, 2023
e933833
test: picker tests pass
liamdebeasi Dec 1, 2023
fc36cc5
add TODOs
liamdebeasi Dec 1, 2023
58a89b3
fix disabled test
liamdebeasi Dec 1, 2023
948c8d8
refactor: cache picker column el
liamdebeasi Dec 1, 2023
7473d64
lint
liamdebeasi Dec 1, 2023
313285d
skip test
liamdebeasi Dec 1, 2023
5a9a7d1
refactor: integrate datetime with picker-column-option
liamdebeasi Dec 4, 2023
8693fd6
refactor: remove default slotted content
liamdebeasi Dec 4, 2023
84c3c52
fix: datetime passes disabled state correctly
liamdebeasi Dec 4, 2023
edb7bad
typo
liamdebeasi Dec 4, 2023
ed8cfa0
chore: remove unused var
liamdebeasi Dec 4, 2023
506f42b
fix: picker-column emits correct payload
liamdebeasi Dec 4, 2023
892a269
test: migrate some datetime tests
liamdebeasi Dec 4, 2023
dc93b8a
test: migrate locale datetime tests
liamdebeasi Dec 4, 2023
656ac5b
test: migrate minmax datetime test
liamdebeasi Dec 4, 2023
cab5646
fix: datetime use keys for stable identity
liamdebeasi Dec 4, 2023
59113bb
test: migrate prefer-wheel tests
liamdebeasi Dec 4, 2023
9562875
fix: picker column option notifies picker column when ready
liamdebeasi Dec 4, 2023
cfcbcd9
fix: picker column selects correct element on scroll
liamdebeasi Dec 4, 2023
3b67bd3
build and lint
liamdebeasi Dec 4, 2023
4b564ee
test: remove .only
liamdebeasi Dec 4, 2023
3da0590
fix(datetime): expose shadow parts
liamdebeasi Dec 4, 2023
514b3b6
fix(picker-column-option): color can be overridden
liamdebeasi Dec 4, 2023
6ddc15f
test(datetime): migrate custom tests
liamdebeasi Dec 4, 2023
6d2f998
chore: lint
liamdebeasi Dec 4, 2023
a524131
add todo
liamdebeasi Dec 4, 2023
90e2d2c
remove outdated comment
liamdebeasi Dec 4, 2023
c1d5401
test(datetime): migrate one more test file
liamdebeasi Dec 4, 2023
e8d5599
Update core/src/components/picker-column/picker-column.tsx
liamdebeasi Dec 5, 2023
d48c41d
use generic for query selector
liamdebeasi Dec 5, 2023
e4797f7
remove explicit type since it can be inferred
liamdebeasi Dec 5, 2023
a98e85d
remove explicit type case
liamdebeasi Dec 5, 2023
33a21d3
remove typecast in favor of generic
liamdebeasi Dec 5, 2023
0ef015b
remove unneeded typecast
liamdebeasi Dec 5, 2023
f9d01b9
remove explicit types
liamdebeasi Dec 5, 2023
cf3d028
active part no longer includes base part
liamdebeasi Dec 5, 2023
d36d645
lint
liamdebeasi Dec 5, 2023
59bd18a
chore: sync
liamdebeasi Dec 5, 2023
fdfc5fc
chore: resolve merge conflicts
liamdebeasi Dec 5, 2023
ca1b519
fix bad merge on api.txt
liamdebeasi Dec 5, 2023
0db0071
Update core/src/components/picker-column-option/picker-column-option.tsx
liamdebeasi Dec 6, 2023
da2db5c
fix: smooth scrolling when value changes
liamdebeasi Dec 6, 2023
4e59020
build
liamdebeasi Dec 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ ion-picker-column,prop,items,PickerColumnItem[],[],false,false
ion-picker-column,prop,mode,"ios" | "md",undefined,false,false
ion-picker-column,prop,value,number | string | undefined,undefined,false,false
ion-picker-column,method,setFocus,setFocus() => Promise<void>
ion-picker-column,event,ionChange,PickerColumnItem,true
ion-picker-column,event,ionChange,{ value: string | number | undefined; },true

ion-picker-column-option,shadow
ion-picker-column-option,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,'primary',false,true
Expand Down
6 changes: 3 additions & 3 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1976,7 +1976,7 @@ export namespace Components {
* If `true`, tapping the picker will reveal a number input keyboard that lets the user type in values for each picker column. This is useful when working with time pickers.
*/
"numericInput": boolean;
"scrollActiveItemIntoView": () => Promise<void>;
"scrollActiveItemIntoView": (smooth?: boolean) => Promise<void>;
/**
* Sets focus on the scrollable container within the picker column. Use this method instead of the global `pickerColumn.focus()`.
*/
Expand Down Expand Up @@ -4055,7 +4055,7 @@ declare global {
new (): HTMLIonPickerElement;
};
interface HTMLIonPickerColumnElementEventMap {
"ionChange": PickerColumnItem;
"ionChange": { value: string | number | undefined };
}
interface HTMLIonPickerColumnElement extends Components.IonPickerColumn, HTMLStencilElement {
addEventListener<K extends keyof HTMLIonPickerColumnElementEventMap>(type: K, listener: (this: HTMLIonPickerColumnElement, ev: IonPickerColumnCustomEvent<HTMLIonPickerColumnElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -6635,7 +6635,7 @@ declare namespace LocalJSX {
/**
* Emitted when the value has changed.
*/
"onIonChange"?: (event: IonPickerColumnCustomEvent<PickerColumnItem>) => void;
"onIonChange"?: (event: IonPickerColumnCustomEvent<{ value: string | number | undefined }>) => void;
/**
* The selected option in the picker.
*/
Expand Down
105 changes: 90 additions & 15 deletions core/src/components/datetime/datetime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,6 @@ export class Datetime implements ComponentInterface {
class="date-column"
color={this.color}
disabled={disabled}
items={items}
value={todayString}
onIonChange={(ev: CustomEvent) => {
// TODO(FW-1823) Remove this when iOS 14 support is dropped.
Expand Down Expand Up @@ -1647,7 +1646,18 @@ export class Datetime implements ComponentInterface {

ev.stopPropagation();
}}
></ion-picker-column>
>
{items.map((item) => (
<ion-picker-column-option
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm observing we are rendering this same JSX mark-up a lot across the component. Thoughts on abstracting this into either a functional component or a shared function that gets invoked with the relevant picker column items?

e.g.:

private renderPickerColumnItems(items: PickerColumnItem[], currentValue: string | number) {
  return (
    items.map(item => (
      <ion-picker-column-option
        part={item.value === currentValue ? WHEEL_ITEM_ACTIVE_PART : WHEEL_ITEM_PART}
        key={item.value}
        disabled={item.disabled}
        value={item.value}
      >
        {item.text}
      </ion-picker-column-option>
    ))
  )
}

Usage (simplified):

<ion-picker-column>
  {this.renderPickerColumnItems(items, todayString)}
</ion-picker-column>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't that mean we would be inconsistent with how ion-picker-column is used in datetime? Right now each render* function renders an ion-picker-column directly in the return statement. The proposed change would keep rendering the duplicate ion-picker-column inline in each render* function but move the ion-picker-column-option components to a separate function.

I'm fine making this change such that we are consistent, but I'd advocate for that to be done separately.

part={item.value === todayString ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART}
key={item.value}
disabled={item.disabled}
value={item.value}
>
{item.text}
</ion-picker-column-option>
))}
</ion-picker-column>
);
}

Expand Down Expand Up @@ -1731,14 +1741,14 @@ export class Datetime implements ComponentInterface {
const { disabled, workingParts } = this;

const activePart = this.getActivePartsWithFallback();
const pickerColumnValue = (workingParts.day !== null ? workingParts.day : this.defaultParts.day) ?? undefined;

return (
<ion-picker-column
class="day-column"
color={this.color}
disabled={disabled}
items={days}
value={(workingParts.day !== null ? workingParts.day : this.defaultParts.day) ?? undefined}
value={pickerColumnValue}
onIonChange={(ev: CustomEvent) => {
// TODO(FW-1823) Remove this when iOS 14 support is dropped.
// Due to a Safari 14 issue we need to destroy
Expand All @@ -1764,7 +1774,18 @@ export class Datetime implements ComponentInterface {

ev.stopPropagation();
}}
></ion-picker-column>
>
{days.map((day) => (
<ion-picker-column-option
part={day.value === pickerColumnValue ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART}
key={day.value}
disabled={day.disabled}
value={day.value}
>
{day.text}
</ion-picker-column-option>
))}
</ion-picker-column>
);
}

Expand All @@ -1782,7 +1803,6 @@ export class Datetime implements ComponentInterface {
class="month-column"
color={this.color}
disabled={disabled}
items={months}
value={workingParts.month}
onIonChange={(ev: CustomEvent) => {
// TODO(FW-1823) Remove this when iOS 14 support is dropped.
Expand All @@ -1809,7 +1829,18 @@ export class Datetime implements ComponentInterface {

ev.stopPropagation();
}}
></ion-picker-column>
>
{months.map((month) => (
<ion-picker-column-option
part={month.value === workingParts.month ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART}
key={month.value}
disabled={month.disabled}
value={month.value}
>
{month.text}
</ion-picker-column-option>
))}
</ion-picker-column>
);
}
private renderYearPickerColumn(years: PickerColumnItem[]) {
Expand All @@ -1826,7 +1857,6 @@ export class Datetime implements ComponentInterface {
class="year-column"
color={this.color}
disabled={disabled}
items={years}
value={workingParts.year}
onIonChange={(ev: CustomEvent) => {
// TODO(FW-1823) Remove this when iOS 14 support is dropped.
Expand All @@ -1853,7 +1883,18 @@ export class Datetime implements ComponentInterface {

ev.stopPropagation();
}}
></ion-picker-column>
>
{years.map((year) => (
<ion-picker-column-option
part={year.value === workingParts.year ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART}
key={year.value}
disabled={year.disabled}
value={year.value}
>
{year.text}
</ion-picker-column-option>
))}
</ion-picker-column>
);
}
private renderTimePickerColumns(forcePresentation: string) {
Expand Down Expand Up @@ -1901,7 +1942,6 @@ export class Datetime implements ComponentInterface {
color={this.color}
disabled={disabled}
value={activePart.hour}
items={hoursData}
numericInput
onIonChange={(ev: CustomEvent) => {
this.setWorkingParts({
Expand All @@ -1916,7 +1956,18 @@ export class Datetime implements ComponentInterface {

ev.stopPropagation();
}}
></ion-picker-column>
>
{hoursData.map((hour) => (
<ion-picker-column-option
part={hour.value === activePart.hour ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART}
key={hour.value}
disabled={hour.disabled}
value={hour.value}
>
{hour.text}
</ion-picker-column-option>
))}
</ion-picker-column>
);
}
private renderMinutePickerColumn(minutesData: PickerColumnItem[]) {
Expand All @@ -1930,7 +1981,6 @@ export class Datetime implements ComponentInterface {
color={this.color}
disabled={disabled}
value={activePart.minute}
items={minutesData}
numericInput
onIonChange={(ev: CustomEvent) => {
this.setWorkingParts({
Expand All @@ -1945,7 +1995,18 @@ export class Datetime implements ComponentInterface {

ev.stopPropagation();
}}
></ion-picker-column>
>
{minutesData.map((minute) => (
<ion-picker-column-option
part={minute.value === activePart.minute ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART}
key={minute.value}
disabled={minute.disabled}
value={minute.value}
>
{minute.text}
</ion-picker-column-option>
))}
</ion-picker-column>
);
}
private renderDayPeriodPickerColumn(dayPeriodData: PickerColumnItem[]) {
Expand All @@ -1963,7 +2024,6 @@ export class Datetime implements ComponentInterface {
color={this.color}
disabled={disabled}
value={activePart.ampm}
items={dayPeriodData}
onIonChange={(ev: CustomEvent) => {
const hour = calculateHourFromAMPM(workingParts, ev.detail.value);

Expand All @@ -1981,7 +2041,20 @@ export class Datetime implements ComponentInterface {

ev.stopPropagation();
}}
></ion-picker-column>
>
{dayPeriodData.map((dayPeriod) => (
<ion-picker-column-option
part={
dayPeriod.value === activePart.ampm ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART
}
key={dayPeriod.value}
disabled={dayPeriod.disabled}
value={dayPeriod.value}
>
{dayPeriod.text}
</ion-picker-column-option>
))}
</ion-picker-column>
);
}

Expand Down Expand Up @@ -2529,3 +2602,5 @@ export class Datetime implements ComponentInterface {
}

let datetimeIds = 0;
const WHEEL_ITEM_PART = 'wheel-item';
const WHEEL_ITEM_ACTIVE_PART = `active`;
4 changes: 2 additions & 2 deletions core/src/components/datetime/test/custom/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@
}

.custom-grid-wheel::part(wheel-item),
ion-picker-column::part(wheel-item) {
ion-picker-column-option {
color: rgb(255, 134, 154);
}

.custom-grid-wheel::part(wheel-item active),
ion-picker-column::part(wheel-item active) {
ion-picker-column-option.option-active {
color: rgb(128, 30, 171);
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/components/datetime/test/datetime.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
page,
}) => {
const monthYearToggle = page.locator('ion-datetime .calendar-month-year');
const monthColumnItems = page.locator('ion-datetime .month-column .picker-item:not(.picker-item-empty)');
const monthColumnItems = page.locator('ion-datetime .month-column ion-picker-column-option');

await expect(monthYearToggle).toContainText('January 2022');

Expand All @@ -34,7 +34,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {

test('should adjust the selected day when moving to a month with a different number of days', async ({ page }) => {
const monthYearToggle = page.locator('ion-datetime .calendar-month-year');
const monthColumnItems = page.locator('ion-datetime .month-column .picker-item:not(.picker-item-empty)');
const monthColumnItems = page.locator('ion-datetime .month-column ion-picker-column-option');
const datetime = page.locator('ion-datetime');
const ionChange = await page.spyOnEvent('ionChange');

Expand Down
5 changes: 2 additions & 3 deletions core/src/components/datetime/test/locale/datetime.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,13 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
test('should correctly localize year column data', async ({ page }) => {
await page.setContent(
`
<ion-datetime prefer-wheel="true" locale="ar-EG" presentation="date" value="2022-01-01"></ion-datetime>
<ion-datetime prefer-wheel="true" locale="ar-EG" presentation="date" value="2022-01-01" max="2022" min="2022"></ion-datetime>
`,
config
);
await page.waitForSelector('.datetime-ready');

const datetimeYear = page.locator('ion-datetime .year-column .picker-item[data-value="2022"]');

const datetimeYear = page.locator('ion-datetime .year-column ion-picker-column-option').nth(0);
await expect(datetimeYear).toHaveText('٢٠٢٢');
});
});
Expand Down
16 changes: 6 additions & 10 deletions core/src/components/datetime/test/minmax/datetime.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +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: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)');
const hours = page.locator('ion-popover ion-picker-column:nth-child(1) ion-picker-column-option');
const minutes = page.locator('ion-popover ion-picker-column:nth-child(2) ion-picker-column-option');

expect(await hours.count()).toBe(12);
expect(await minutes.count()).toBe(60);
Expand Down Expand Up @@ -214,9 +214,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
config
);

const hourPickerItems = page.locator(
'ion-datetime ion-picker-column:first-of-type .picker-item:not(.picker-item-empty)'
);
const hourPickerItems = page.locator('ion-datetime ion-picker-column:first-of-type ion-picker-column-option');
await expect(hourPickerItems).toHaveText(['8', '9', '10', '11']);
});

Expand All @@ -238,9 +236,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
config
);

const hourPickerItems = page.locator(
'ion-datetime ion-picker-column:first-of-type .picker-item:not(.picker-item-empty)'
);
const hourPickerItems = page.locator('ion-datetime ion-picker-column:first-of-type ion-picker-column-option');
await expect(hourPickerItems).toHaveText(['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']);
});

Expand Down Expand Up @@ -304,7 +300,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
);

const datetime = page.locator('ion-datetime');
const monthColumnItems = page.locator('ion-datetime .month-column .picker-item:not(.picker-item-empty)');
const monthColumnItems = page.locator('ion-datetime .month-column ion-picker-column-option');
const ionChange = await page.spyOnEvent('ionChange');

await page.waitForSelector('.datetime-ready');
Expand Down Expand Up @@ -356,7 +352,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>

await ionPopoverDidPresent.next();

const hours = page.locator('ion-popover ion-picker-column:nth-child(1) .picker-item:not(.picker-item-empty)');
const hours = page.locator('ion-popover ion-picker-column:nth-child(1) ion-picker-column-option');

await expect(await hours.count()).toBe(4);
});
Expand Down
Loading