Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ed7f7a8
fix(datetime): allow disabling datetime with prefer-wheel
mapsandapps Nov 10, 2023
b7e42be
chore(): add updated snapshots
Ionitron Nov 10, 2023
254294e
Merge branch 'main' into FW-5408
mapsandapps Nov 13, 2023
be8f483
Convert test
mapsandapps Nov 14, 2023
41b6369
Improve test (still failing)
mapsandapps Nov 14, 2023
031e9ab
Fix test
mapsandapps Nov 14, 2023
0bab06e
Merge branch 'main' into FW-5408
mapsandapps Nov 14, 2023
aff808a
Rearrange styles
mapsandapps Nov 15, 2023
eb3dd1d
Merge branch 'main' into FW-5408
mapsandapps Nov 15, 2023
c5c6405
Merge branch 'main' into FW-5408
mapsandapps Nov 16, 2023
b2b4116
Refactor & address PR feedback
mapsandapps Nov 17, 2023
549a11f
Fix refactoring typo
mapsandapps Nov 17, 2023
9759820
Make IntersectionObserver mocking more consistent
mapsandapps Nov 17, 2023
8477187
Fix styles
mapsandapps Nov 17, 2023
d8d04be
Simplify selector
mapsandapps Nov 20, 2023
450448c
Address PR feedback
mapsandapps Nov 20, 2023
048bb82
Address PR feedback
mapsandapps Nov 21, 2023
b15fbfa
Address PR feedback
mapsandapps Nov 21, 2023
7a3771a
Try to fix flaky test
mapsandapps Nov 21, 2023
4661667
Try to fix test by setting value initially
mapsandapps Nov 21, 2023
d49a495
Revert 7a3771a
mapsandapps Nov 21, 2023
845ecb3
Set value on element
mapsandapps Nov 21, 2023
c86735f
Add snapshot test for disabled datetime with wheel
mapsandapps Nov 21, 2023
ffec723
chore(): add updated snapshots
Ionitron Nov 22, 2023
fab89a7
test: remove redundant test
liamdebeasi Nov 22, 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
8 changes: 8 additions & 0 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2043,6 +2043,10 @@ export namespace Components {
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, the user cannot interact with the picker.
*/
"disabled": boolean;
/**
* A list of options to be displayed in the picker
*/
Expand Down Expand Up @@ -6683,6 +6687,10 @@ declare namespace LocalJSX {
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, the user cannot interact with the picker.
*/
"disabled"?: boolean;
/**
* A list of options to be displayed in the picker
*/
Expand Down
21 changes: 14 additions & 7 deletions core/src/components/datetime/datetime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,7 @@ export class Datetime implements ComponentInterface {
}

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

const activePart = this.getActivePartsWithFallback();

Expand Down Expand Up @@ -1604,6 +1604,7 @@ export class Datetime implements ComponentInterface {
<ion-picker-column-internal
class="date-column"
color={this.color}
disabled={disabled}
items={items}
value={todayString}
onIonChange={(ev: CustomEvent) => {
Expand Down Expand Up @@ -1715,14 +1716,15 @@ export class Datetime implements ComponentInterface {
return [];
}

const { workingParts } = this;
const { disabled, workingParts } = this;

const activePart = this.getActivePartsWithFallback();

return (
<ion-picker-column-internal
class="day-column"
color={this.color}
disabled={disabled}
items={days}
value={(workingParts.day !== null ? workingParts.day : this.defaultParts.day) ?? undefined}
onIonChange={(ev: CustomEvent) => {
Expand Down Expand Up @@ -1759,14 +1761,15 @@ export class Datetime implements ComponentInterface {
return [];
}

const { workingParts } = this;
const { disabled, workingParts } = this;

const activePart = this.getActivePartsWithFallback();

return (
<ion-picker-column-internal
class="month-column"
color={this.color}
disabled={disabled}
items={months}
value={workingParts.month}
onIonChange={(ev: CustomEvent) => {
Expand Down Expand Up @@ -1802,14 +1805,15 @@ export class Datetime implements ComponentInterface {
return [];
}

const { workingParts } = this;
const { disabled, workingParts } = this;

const activePart = this.getActivePartsWithFallback();

return (
<ion-picker-column-internal
class="year-column"
color={this.color}
disabled={disabled}
items={years}
value={workingParts.year}
onIonChange={(ev: CustomEvent) => {
Expand Down Expand Up @@ -1875,14 +1879,15 @@ export class Datetime implements ComponentInterface {
}

private renderHourPickerColumn(hoursData: PickerColumnItem[]) {
const { workingParts } = this;
const { disabled, workingParts } = this;
if (hoursData.length === 0) return [];

const activePart = this.getActivePartsWithFallback();

return (
<ion-picker-column-internal
color={this.color}
disabled={disabled}
value={activePart.hour}
items={hoursData}
numericInput
Expand All @@ -1903,14 +1908,15 @@ export class Datetime implements ComponentInterface {
);
}
private renderMinutePickerColumn(minutesData: PickerColumnItem[]) {
const { workingParts } = this;
const { disabled, workingParts } = this;
if (minutesData.length === 0) return [];

const activePart = this.getActivePartsWithFallback();

return (
<ion-picker-column-internal
color={this.color}
disabled={disabled}
value={activePart.minute}
items={minutesData}
numericInput
Expand All @@ -1931,7 +1937,7 @@ export class Datetime implements ComponentInterface {
);
}
private renderDayPeriodPickerColumn(dayPeriodData: PickerColumnItem[]) {
const { workingParts } = this;
const { disabled, workingParts } = this;
if (dayPeriodData.length === 0) {
return [];
}
Expand All @@ -1943,6 +1949,7 @@ export class Datetime implements ComponentInterface {
<ion-picker-column-internal
style={isDayPeriodRTL ? { order: '-1' } : {}}
color={this.color}
disabled={disabled}
value={activePart.ampm}
items={dayPeriodData}
onIonChange={(ev: CustomEvent) => {
Expand Down
39 changes: 39 additions & 0 deletions core/src/components/datetime/test/disabled/datetime.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
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';

describe('ion-datetime disabled', () => {
beforeEach(() => {
// IntersectionObserver isn't available in test environment
const mockIntersectionObserver = jest.fn();
mockIntersectionObserver.mockReturnValue({
observe: () => null,
unobserve: () => null,
disconnect: () => null,
});
global.IntersectionObserver = mockIntersectionObserver;
});

it('picker should be disabled in prefer wheel mode', async () => {
const page = await newSpecPage({
components: [Datetime, PickerColumnInternal, PickerInternal],
template: () => (
<ion-datetime id="inline-datetime-wheel" disabled prefer-wheel value="2022-04-21T00:00:00"></ion-datetime>
),
});

await page.waitForChanges();

const datetime = page.body.querySelector('ion-datetime')!;
const columns = datetime.shadowRoot!.querySelectorAll('ion-picker-column-internal');

await expect(columns.length).toEqual(4);

columns.forEach((column) => {
expect(column.disabled).toBe(true);
});
});
});
5 changes: 5 additions & 0 deletions core/src/components/datetime/test/disabled/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ <h2>Inline</h2>
<h2>Inline - No Default Value</h2>
<ion-datetime id="inline-datetime-no-value" disabled></ion-datetime>
</div>

<div class="grid-item">
<h2>Inline - Prefer Wheel</h2>
<ion-datetime id="inline-datetime-wheel" disabled prefer-wheel value="2022-04-21T00:00:00"></ion-datetime>
</div>
</div>
</ion-content>
<script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,20 @@
}

:host .picker-item-empty,
:host .picker-item.picker-item-disabled {
:host .picker-item[disabled] {
cursor: default;
}

:host .picker-item-empty,
:host(:not([disabled])) .picker-item[disabled] {
scroll-snap-align: none;
}

cursor: default;
:host([disabled]) {
overflow-y: hidden;
}

:host .picker-item.picker-item-disabled {
:host .picker-item[disabled] {
opacity: 0.4;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ export class PickerColumnInternal implements ComponentInterface {

@Element() el!: HTMLIonPickerColumnInternalElement;

/**
* If `true`, the user cannot interact with the picker.
*/
@Prop() disabled = false;

/**
* A list of options to be displayed in the picker
*/
Expand Down Expand Up @@ -408,13 +413,15 @@ export class PickerColumnInternal implements ComponentInterface {
};

get activeItem() {
return getElementRoot(this.el).querySelector(
`.picker-item[data-value="${this.value}"]:not([disabled])`
) as HTMLElement | null;
// If the whole picker column is disabled, the current value should appear active
// If the current value item is specifically disabled, it should not appear active
const selector = `.picker-item[data-value="${this.value}"]${this.disabled ? '' : ':not([disabled])'}`;

return getElementRoot(this.el).querySelector(selector) as HTMLElement | null;
}

render() {
const { items, color, isActive, numericInput } = this;
const { items, color, disabled: pickerDisabled, isActive, numericInput } = this;
Comment thread
sean-perkins marked this conversation as resolved.
const mode = getIonMode(this);

/**
Expand All @@ -423,10 +430,12 @@ export class PickerColumnInternal implements ComponentInterface {
* the attribute can be moved to datetime.tsx and set on every
* instance of ion-picker-column-internal there instead.
*/

return (
<Host
exportparts={`${PICKER_ITEM_PART}, ${PICKER_ITEM_ACTIVE_PART}`}
tabindex={0}
disabled={pickerDisabled}
tabindex={pickerDisabled ? null : 0}
class={createColorClasses(color, {
[mode]: true,
['picker-column-active']: isActive,
Expand All @@ -443,6 +452,8 @@ export class PickerColumnInternal implements ComponentInterface {
&nbsp;
</div>
{items.map((item, index) => {
const isItemDisabled = pickerDisabled || item.disabled || false;
Comment thread
mapsandapps marked this conversation as resolved.

{
/*
Users should be able to tab
Expand All @@ -458,14 +469,13 @@ export class PickerColumnInternal implements ComponentInterface {
tabindex="-1"
class={{
'picker-item': true,
'picker-item-disabled': item.disabled || false,
}}
data-value={item.value}
data-index={index}
onClick={(ev: Event) => {
this.centerPickerItemInView(ev.target as HTMLElement, true);
}}
disabled={item.disabled}
disabled={isItemDisabled}
part={PICKER_ITEM_PART}
>
{item.text}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,39 @@
<ion-content class="ion-padding">
<div class="grid">
<div class="grid-item">
<h2>Default</h2>
<h2>Even items disabled</h2>
<ion-picker-internal>
<ion-picker-column-internal id="default"></ion-picker-column-internal>
<ion-picker-column-internal id="half-disabled"></ion-picker-column-internal>
</ion-picker-internal>
</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>
</div>
</div>
</ion-content>
<script>
const defaultPickerColumn = document.getElementById('default');

const items = Array(24)
const halfDisabledPicker = document.getElementById('half-disabled');
const halfDisabledItems = Array(24)
.fill()
.map((_, i) => ({
text: `${i}`,
value: i,
disabled: i % 2 === 0,
}));
halfDisabledPicker.items = halfDisabledItems;
halfDisabledPicker.value = 12;

defaultPickerColumn.items = items;
defaultPickerColumn.value = 12;
const fullDisabledPicker = document.getElementById('column-disabled');
const items = Array(24)
.fill()
.map((_, i) => ({
text: `${i}`,
value: i,
}));
fullDisabledPicker.items = items;
</script>
</ion-app>
</body>
Expand Down
Loading