Skip to content

feat(datetime): add preferWheel support for date-time and time-date presentation #25432

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 94 commits into from
Jun 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
42f47f5
feat(datetime): add preferWheel property
liamdebeasi May 31, 2022
50cad69
test(datetime): add base preferWheel test file
liamdebeasi May 31, 2022
cf39191
refactor(datetime): extract wheel picker to separate function that ha…
liamdebeasi May 31, 2022
fbb9f14
refactor(): add time to combined wheel picker
liamdebeasi May 31, 2022
3172433
fix(): add missing forcePresentation
liamdebeasi May 31, 2022
3d57b00
chore(): lint
liamdebeasi May 31, 2022
d5c63d8
fix(): always render [] instead of undefined
liamdebeasi May 31, 2022
ab2a5aa
chore(): clean up
liamdebeasi May 31, 2022
530cc23
chore(): remove test
liamdebeasi May 31, 2022
5c26cea
refactor(datetime): add renderDateColumns method
liamdebeasi May 31, 2022
f9548a7
refactor(): revert month and year render function changes
liamdebeasi May 31, 2022
ad69a0b
refactor(): revert time picker column change
liamdebeasi May 31, 2022
aeee7a7
test(datetime): add base test file
liamdebeasi May 31, 2022
82468c9
refactor(): only toggled month/year gets month-year class
liamdebeasi May 31, 2022
083eca9
feat(datetime): add day selection to wheel picker
liamdebeasi May 31, 2022
531b817
fix(datetime): month/day/year locale ordering works
liamdebeasi May 31, 2022
31eea67
test(datetime): add test for date wheel
liamdebeasi May 31, 2022
6fb7166
chore(): simplify test
liamdebeasi Jun 1, 2022
6ec7517
chore(): add missing locator
liamdebeasi Jun 1, 2022
f77cd0b
refactor(datetime): get date data in top level renderDatePickerColumns
liamdebeasi Jun 1, 2022
81ac6d2
chore(): plural
liamdebeasi Jun 1, 2022
9cd917a
feat(picker-interal): add ability to disable picker items
liamdebeasi Jun 1, 2022
188f702
fix(): do not include disabled items in search
liamdebeasi Jun 1, 2022
ed40628
fix(picker-internal): disabled buttons no longer have cursor pointer
liamdebeasi Jun 1, 2022
b0d9359
fix(picker-internal): fix color on ios
liamdebeasi Jun 1, 2022
5fdc0c1
Merge remote-tracking branch 'origin/picker-disable' into wheel-date
liamdebeasi Jun 1, 2022
79e7bdf
chore(): stub date enable implementation
liamdebeasi Jun 1, 2022
45dc742
chore(): update e2e
liamdebeasi Jun 1, 2022
c915fbb
fix(picker-internal): do not highlight disabled items
liamdebeasi Jun 1, 2022
3373d23
Merge remote-tracking branch 'origin/picker-disable' into wheel-date
liamdebeasi Jun 1, 2022
783bfa1
fix(datetime): date wheel picker now accounts for isDateEnabled
liamdebeasi Jun 1, 2022
2b5c468
chore(): clean up
liamdebeasi Jun 1, 2022
9abaaff
test(datetime): check isDateEnabled functionality
liamdebeasi Jun 2, 2022
ce2764f
chore(): lint
liamdebeasi Jun 2, 2022
d59a317
Merge remote-tracking branch 'origin/picker-disable' into wheel-date
liamdebeasi Jun 2, 2022
60490cc
chore(): remove log
liamdebeasi Jun 2, 2022
aa3f8e6
test(datetime): validate month/day/year value props
liamdebeasi Jun 2, 2022
6c90521
chore(): lint
liamdebeasi Jun 2, 2022
bafb4ae
chore(): remove only
liamdebeasi Jun 2, 2022
38d5935
chore(): add stub for combined wheel picker
liamdebeasi Jun 2, 2022
758b1e1
feat(datetime): basic implementation of wheel for date-time
liamdebeasi Jun 2, 2022
f2201d4
feat(datetime): add localization support, clean up code
liamdebeasi Jun 3, 2022
4f08ed2
feat(datetime): add initial wheel date implementation
liamdebeasi Jun 7, 2022
f02b8f8
test(datetime): add initial tests
liamdebeasi Jun 7, 2022
ab1421a
chore(): simplify test
liamdebeasi Jun 7, 2022
2094f5f
test(datetime): add isDateEnabled and values tests
liamdebeasi Jun 7, 2022
4f1006b
refactor(): get data from parent fn and pass to children
liamdebeasi Jun 7, 2022
7e83f64
chore(): typo
liamdebeasi Jun 7, 2022
c12c0b0
chore(): more typos
liamdebeasi Jun 7, 2022
6d78124
feat(datetime): add support for isDateEnabled
liamdebeasi Jun 7, 2022
dae3c2b
chore(): lint
liamdebeasi Jun 7, 2022
f33dd22
chore(): comments
liamdebeasi Jun 7, 2022
d7cda50
Merge remote-tracking branch 'origin/FW-225' into wheel-date-2
liamdebeasi Jun 7, 2022
ab2b981
test(datetime): add localization test
liamdebeasi Jun 7, 2022
d7a93a9
fix(datetime): resolve calendar grid wheel picker regression
liamdebeasi Jun 7, 2022
9719a64
chore(): force new cache creation
liamdebeasi Jun 7, 2022
8db45f6
chore(): avoid bad cache
liamdebeasi Jun 7, 2022
60f87f6
chore(): lint
liamdebeasi Jun 7, 2022
2eb4857
chore(): add updated snapshots
Ionitron Jun 7, 2022
0ffed13
chore(): fix test
liamdebeasi Jun 8, 2022
d8aeb2c
chore(): fix other test
liamdebeasi Jun 8, 2022
ad32334
chore(): fix test for real this time
liamdebeasi Jun 8, 2022
db05caa
fix(datetime): add correct sizing on ios
liamdebeasi Jun 8, 2022
0015993
test(datetime): add tests
liamdebeasi Jun 8, 2022
156adc1
chore(): add todo
liamdebeasi Jun 8, 2022
43d78fe
chore(): remove log
liamdebeasi Jun 8, 2022
e648f8d
fix(datetime): add confirm value functionality
liamdebeasi Jun 8, 2022
9072b86
fix(datetime): add date-time wheel isDateEnabled functionality
liamdebeasi Jun 8, 2022
8dbdd07
fix(datetime): avoid layout shift with wheel picker
liamdebeasi Jun 8, 2022
e2477b0
chore(); sync with wheel-date
liamdebeasi Jun 8, 2022
211f748
chore(): clean up
liamdebeasi Jun 8, 2022
1919ef3
fix(datetime): time-date ordering now appears correctly
liamdebeasi Jun 8, 2022
5794fe4
chore(): fix order
liamdebeasi Jun 8, 2022
805b9ad
chore(): fix min width on tests
liamdebeasi Jun 8, 2022
e8b4332
chore(): fix screenshot sizing
liamdebeasi Jun 8, 2022
2ba2b3f
chore(): increase width
liamdebeasi Jun 8, 2022
b858fec
chore(): fix test
liamdebeasi Jun 8, 2022
b9080ad
chore(): add updated snapshots
Ionitron Jun 8, 2022
647b6f8
Merge remote-tracking branch 'origin/FW-225' into wheel-date-2
liamdebeasi Jun 8, 2022
0913d61
chore: revert screenshot
liamdebeasi Jun 8, 2022
9a45f38
chore(): add updated snapshots
Ionitron Jun 8, 2022
3bcea1b
chore(): sync
liamdebeasi Jun 8, 2022
b3bf9f2
chore(): add updated snapshots
Ionitron Jun 8, 2022
0f3209e
chore(): sync with FW-225
liamdebeasi Jun 9, 2022
a0b8282
chore(): bust cache
liamdebeasi Jun 9, 2022
3d23942
Merge remote-tracking branch 'origin/FW-225' into wheel-date-time-2
liamdebeasi Jun 9, 2022
bd53423
chore(): sync with FW-225
liamdebeasi Jun 9, 2022
f434e99
chore(): add updated snapshots
Ionitron Jun 9, 2022
45d20ee
fix(picker-column-internal): disabled items are grayed out
liamdebeasi Jun 13, 2022
6bed4ee
Merge branch 'wheel-date-time-2' of https://github.com/ionic-team/ion…
liamdebeasi Jun 13, 2022
5fe1dc3
Update core/src/components/datetime/datetime.tsx
liamdebeasi Jun 13, 2022
3ad5994
chore(): add updated snapshots
Ionitron Jun 13, 2022
167da1c
chore(): prettier
liamdebeasi Jun 13, 2022
6e4b29f
chore(): add todo
liamdebeasi Jun 13, 2022
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
6 changes: 3 additions & 3 deletions core/src/components/datetime/datetime.ios.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
--title-color: #{$text-color-step-400};
}

:host(.datetime-presentation-date-time),
:host(.datetime-presentation-time-date),
:host(.datetime-presentation-date) {
:host(.datetime-presentation-date-time:not(.datetime-prefer-wheel)),
:host(.datetime-presentation-time-date:not(.datetime-prefer-wheel)),
:host(.datetime-presentation-date:not(.datetime-prefer-wheel)) {
min-height: 350px;
}

Expand Down
152 changes: 145 additions & 7 deletions core/src/components/datetime/datetime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
getDayColumnData,
getYearColumnData,
getTimeColumnsData,
getCombinedDateColumnData,
} from './utils/data';
import { getFormattedTime, getMonthAndDay, getMonthAndYear } from './utils/format';
import { is24Hour, isMonthFirstLocale } from './utils/helpers';
Expand Down Expand Up @@ -1261,15 +1262,138 @@ export class Datetime implements ComponentInterface {
*/

private renderWheelPicker(forcePresentation: string = this.presentation) {
/**
* If presentation="time-date" we switch the
* order of the render array here instead of
* manually reordering each date/time picker
* column with CSS. This allows for additional
* flexibility if we need to render subsets
* of the date/time data or do additional ordering
* within the child render functions.
*/
const renderArray =
forcePresentation === 'time-date'
? [this.renderTimePickerColumns(forcePresentation), this.renderDatePickerColumns(forcePresentation)]
: [this.renderDatePickerColumns(forcePresentation), this.renderTimePickerColumns(forcePresentation)];
return <ion-picker-internal>{renderArray}</ion-picker-internal>;
}

private renderDatePickerColumns(forcePresentation: string) {
return forcePresentation === 'date-time' || forcePresentation === 'time-date'
? this.renderCombinedDatePickerColumn()
: this.renderIndividualDatePickerColumns(forcePresentation);
}

private renderCombinedDatePickerColumn() {
const { workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;

/**
* By default, generate a range of 3 months:
* Previous month, current month, and next month
*/
const monthsToRender = generateMonths(workingParts);

/**
* generateMonths returns the day data as well,
* but we do not want the day value to act as a max/min
* on the data we are going to generate.
*/
for (let i = 0; i <= monthsToRender.length - 1; i++) {
monthsToRender[i].day = null;
}

/**
* If developers have provided their own
* min/max values, use that instead. Otherwise,
* fallback to the default range of 3 months.
*/
const min = minParts || monthsToRender[0];
const max = maxParts || monthsToRender[monthsToRender.length - 1];

const result = getCombinedDateColumnData(
locale,
workingParts,
todayParts,
min,
max,
this.parsedDayValues,
this.parsedMonthValues
);
let items = result.items;
const parts = result.parts;

if (isDateEnabled) {
items = items.map((itemObject, index) => {
const referenceParts = parts[index];

let disabled;
try {
/**
* The `isDateEnabled` implementation is try-catch wrapped
* to prevent exceptions in the user's function from
* interrupting the calendar rendering.
*/
disabled = !isDateEnabled(convertDataToISO(referenceParts));
} catch (e) {
printIonError(
'Exception thrown from provided `isDateEnabled` function. Please check your function and try again.',
e
);
}

return {
...itemObject,
disabled,
};
});
}

/**
* If we have selected a day already, then default the column
* to that value. Otherwise, default it to today.
*/
const todayString = workingParts.day
? `${workingParts.year}-${workingParts.month}-${workingParts.day}`
: `${todayParts.year}-${todayParts.month}-${todayParts.day}`;

return (
<ion-picker-internal>
{this.renderDatePickerColumns(forcePresentation)}
{this.renderTimePickerColumns(forcePresentation)}
</ion-picker-internal>
<ion-picker-column-internal
class="date-column"
color={this.color}
items={items}
value={todayString}
onIonChange={(ev: CustomEvent) => {
// Due to a Safari 14 issue we need to destroy
// the intersection observer before we update state
// and trigger a re-render.
if (this.destroyCalendarIO) {
this.destroyCalendarIO();
}

const { value } = ev.detail;
const findPart = parts.find(({ month, day, year }) => value === `${year}-${month}-${day}`);

this.setWorkingParts({
...this.workingParts,
...findPart,
});

this.setActiveParts({
...this.activeParts,
...findPart,
});

// We can re-attach the intersection observer after
// the working parts have been updated.
this.initializeCalendarIOListeners();

ev.stopPropagation();
}}
></ion-picker-column-internal>
);
}

private renderDatePickerColumns(forcePresentation: string) {
private renderIndividualDatePickerColumns(forcePresentation: string) {
const { workingParts, isDateEnabled } = this;
const shouldRenderMonths = forcePresentation !== 'year' && forcePresentation !== 'time';
const months = shouldRenderMonths
Expand Down Expand Up @@ -1803,7 +1927,6 @@ export class Datetime implements ComponentInterface {
</ion-popover>,
];
}

private renderCalendarViewHeader(mode: Mode) {
const hasSlottedTitle = this.el.querySelector('[slot="title"]') !== null;
if (!hasSlottedTitle && !this.showDefaultTitle) {
Expand Down Expand Up @@ -1899,12 +2022,26 @@ export class Datetime implements ComponentInterface {
}

render() {
const { name, value, disabled, el, color, isPresented, readonly, showMonthAndYear, presentation, size } = this;
const {
name,
value,
disabled,
el,
color,
isPresented,
readonly,
showMonthAndYear,
preferWheel,
presentation,
size,
} = this;
const mode = getIonMode(this);
const isMonthAndYearPresentation =
presentation === 'year' || presentation === 'month' || presentation === 'month-year';
const shouldShowMonthAndYear = showMonthAndYear || isMonthAndYearPresentation;
const monthYearPickerOpen = showMonthAndYear && !isMonthAndYearPresentation;
const hasWheelVariant =
(presentation === 'date' || presentation === 'date-time' || presentation === 'time-date') && preferWheel;

renderHiddenInput(true, el, name, value, disabled);

Expand All @@ -1923,6 +2060,7 @@ export class Datetime implements ComponentInterface {
'month-year-picker-open': monthYearPickerOpen,
[`datetime-presentation-${presentation}`]: true,
[`datetime-size-${size}`]: true,
[`datetime-prefer-wheel`]: hasWheelVariant,
}),
}}
>
Expand Down
Loading