Skip to content

Commit ac39d58

Browse files
committed
Merge branch 'feature-8.8' into FW-6582
2 parents 6741093 + 822da42 commit ac39d58

23 files changed

Lines changed: 443 additions & 22 deletions

File tree

core/api.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ ion-datetime,part,calendar-day today
569569
ion-datetime,part,month-year-button
570570
ion-datetime,part,time-button
571571
ion-datetime,part,time-button active
572+
ion-datetime,part,wheel
572573
ion-datetime,part,wheel-item
573574
ion-datetime,part,wheel-item active
574575

core/src/components/datetime/datetime.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ import { checkForPresentationFormatMismatch, warnIfTimeZoneProvided } from './ut
7979
* @slot buttons - The buttons in the datetime.
8080
* @slot time-label - The label for the time selector in the datetime.
8181
*
82+
* @part wheel - The wheel container when using a wheel style layout, or in the month/year picker when using a grid style layout.
8283
* @part wheel-item - The individual items when using a wheel style layout, or in the
8384
* month/year picker when using a grid style layout.
8485
* @part wheel-item active - The currently selected wheel-item.
@@ -1724,6 +1725,7 @@ export class Datetime implements ComponentInterface {
17241725

17251726
return (
17261727
<ion-picker-column
1728+
part={WHEEL_PART}
17271729
aria-label="Select a date"
17281730
class="date-column"
17291731
color={this.color}
@@ -1844,6 +1846,7 @@ export class Datetime implements ComponentInterface {
18441846

18451847
return (
18461848
<ion-picker-column
1849+
part={WHEEL_PART}
18471850
aria-label="Select a day"
18481851
class="day-column"
18491852
color={this.color}
@@ -1888,6 +1891,7 @@ export class Datetime implements ComponentInterface {
18881891

18891892
return (
18901893
<ion-picker-column
1894+
part={WHEEL_PART}
18911895
aria-label="Select a month"
18921896
class="month-column"
18931897
color={this.color}
@@ -1931,6 +1935,7 @@ export class Datetime implements ComponentInterface {
19311935

19321936
return (
19331937
<ion-picker-column
1938+
part={WHEEL_PART}
19341939
aria-label="Select a year"
19351940
class="year-column"
19361941
color={this.color}
@@ -2005,6 +2010,7 @@ export class Datetime implements ComponentInterface {
20052010

20062011
return (
20072012
<ion-picker-column
2013+
part={WHEEL_PART}
20082014
aria-label="Select an hour"
20092015
color={this.color}
20102016
disabled={disabled}
@@ -2045,6 +2051,7 @@ export class Datetime implements ComponentInterface {
20452051

20462052
return (
20472053
<ion-picker-column
2054+
part={WHEEL_PART}
20482055
aria-label="Select a minute"
20492056
color={this.color}
20502057
disabled={disabled}
@@ -2088,6 +2095,7 @@ export class Datetime implements ComponentInterface {
20882095

20892096
return (
20902097
<ion-picker-column
2098+
part={WHEEL_PART}
20912099
aria-label="Select a day period"
20922100
style={isDayPeriodRTL ? { order: '-1' } : {}}
20932101
color={this.color}
@@ -2716,5 +2724,6 @@ export class Datetime implements ComponentInterface {
27162724
let datetimeIds = 0;
27172725
const CANCEL_ROLE = 'datetime-cancel';
27182726
const CONFIRM_ROLE = 'datetime-confirm';
2727+
const WHEEL_PART = 'wheel';
27192728
const WHEEL_ITEM_PART = 'wheel-item';
27202729
const WHEEL_ITEM_ACTIVE_PART = `active`;

core/src/components/datetime/test/custom/datetime.e2e.ts

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,140 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
4242
await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-calendar-days`));
4343
});
4444
});
45+
46+
test.describe(title('CSS shadow parts'), () => {
47+
test('should be able to customize wheel part within the wheel style', async ({ page }, testInfo) => {
48+
testInfo.annotations.push({
49+
type: 'issue',
50+
description: 'https://github.com/ionic-team/ionic-framework/issues/30420',
51+
});
52+
53+
await page.setContent(
54+
`
55+
<style>
56+
ion-datetime::part(wheel) {
57+
background-color: red;
58+
}
59+
</style>
60+
<ion-datetime
61+
prefer-wheel="true"
62+
value="2020-03-14T14:23:00.000Z"
63+
></ion-datetime>
64+
`,
65+
config
66+
);
67+
68+
const datetime = page.locator('ion-datetime');
69+
const pickerColumn = datetime.locator('ion-picker-column').first();
70+
71+
const backgroundColor = await pickerColumn.evaluate((el) => {
72+
return window.getComputedStyle(el).backgroundColor;
73+
});
74+
75+
expect(backgroundColor).toBe('rgb(255, 0, 0)');
76+
});
77+
78+
test('should be able to customize wheel part within the month/year picker', async ({ page }, testInfo) => {
79+
testInfo.annotations.push({
80+
type: 'issue',
81+
description: 'https://github.com/ionic-team/ionic-framework/issues/30420',
82+
});
83+
84+
await page.setContent(
85+
`
86+
<style>
87+
ion-datetime::part(wheel) {
88+
background-color: orange;
89+
}
90+
</style>
91+
<ion-datetime
92+
value="2020-03-14T14:23:00.000Z"
93+
></ion-datetime>
94+
`,
95+
config
96+
);
97+
98+
const datetime = page.locator('ion-datetime');
99+
const monthYearButton = datetime.locator('.calendar-month-year-toggle');
100+
101+
await monthYearButton.click();
102+
103+
const pickerColumn = datetime.locator('ion-picker-column').first();
104+
105+
const backgroundColor = await pickerColumn.evaluate((el) => {
106+
return window.getComputedStyle(el).backgroundColor;
107+
});
108+
109+
expect(backgroundColor).toBe('rgb(255, 165, 0)');
110+
});
111+
112+
test('should be able to customize wheel part within the time picker', async ({ page }, testInfo) => {
113+
testInfo.annotations.push({
114+
type: 'issue',
115+
description: 'https://github.com/ionic-team/ionic-framework/issues/30420',
116+
});
117+
118+
await page.setContent(
119+
`
120+
<style>
121+
ion-picker-column {
122+
background-color: green;
123+
}
124+
</style>
125+
<ion-datetime
126+
value="2020-03-14T14:23:00.000Z"
127+
></ion-datetime>
128+
`,
129+
config
130+
);
131+
132+
const datetime = page.locator('ion-datetime');
133+
const timeButton = datetime.locator('.time-body');
134+
135+
await timeButton.click();
136+
137+
const pickerColumn = page.locator('ion-picker-column').first();
138+
139+
const backgroundColor = await pickerColumn.evaluate((el) => {
140+
return window.getComputedStyle(el).backgroundColor;
141+
});
142+
143+
expect(backgroundColor).toBe('rgb(0, 128, 0)');
144+
});
145+
146+
test('should be able to customize wheel part when focused', async ({ page }, testInfo) => {
147+
testInfo.annotations.push({
148+
type: 'issue',
149+
description: 'https://github.com/ionic-team/ionic-framework/issues/30420',
150+
});
151+
152+
await page.setContent(
153+
`
154+
<style>
155+
ion-datetime::part(wheel):focus {
156+
background-color: blue;
157+
}
158+
</style>
159+
<ion-datetime
160+
prefer-wheel="true"
161+
value="2020-03-14T14:23:00.000Z"
162+
></ion-datetime>
163+
`,
164+
config
165+
);
166+
167+
const datetime = page.locator('ion-datetime');
168+
const pickerColumn = datetime.locator('ion-picker-column').first();
169+
170+
await pickerColumn.click({ position: { x: 10, y: 10 } });
171+
172+
const backgroundColor = await pickerColumn.evaluate((el) => {
173+
return window.getComputedStyle(el).backgroundColor;
174+
});
175+
176+
expect(backgroundColor).toBe('rgb(0, 0, 255)');
177+
});
178+
});
45179
});
46180

47181
/**

core/src/components/datetime/test/custom/index.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@
7474
color: rgb(128, 30, 171);
7575
}
7676

77+
/* Targets the month/year picker and the wheel style datetime */
78+
.custom-grid-wheel::part(wheel):focus,
79+
/* Targets the time picker */
80+
ion-picker-column:focus {
81+
background-color: rgba(138, 238, 69, 0.37);
82+
}
83+
7784
/*
7885
* Custom Datetime Day Parts
7986
* -------------------------------------------

packages/angular/common/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export { AngularDelegate, bindLifecycleEvents, IonModalToken } from './providers
99

1010
export type { IonicWindow } from './types/interfaces';
1111
export type { ViewDidEnter, ViewDidLeave, ViewWillEnter, ViewWillLeave } from './types/ionic-lifecycle-hooks';
12+
export type { ModalOptions, PopoverOptions } from './types/overlay-options';
1213

1314
export { NavParams } from './directives/navigation/nav-params';
1415

packages/angular/common/src/providers/angular-delegate.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,17 @@ export class AngularDelegate {
3636
create(
3737
environmentInjector: EnvironmentInjector,
3838
injector: Injector,
39-
elementReferenceKey?: string
39+
elementReferenceKey?: string,
40+
customInjector?: Injector
4041
): AngularFrameworkDelegate {
4142
return new AngularFrameworkDelegate(
4243
environmentInjector,
4344
injector,
4445
this.applicationRef,
4546
this.zone,
4647
elementReferenceKey,
47-
this.config.useSetInputAPI ?? false
48+
this.config.useSetInputAPI ?? false,
49+
customInjector
4850
);
4951
}
5052
}
@@ -59,7 +61,8 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
5961
private applicationRef: ApplicationRef,
6062
private zone: NgZone,
6163
private elementReferenceKey?: string,
62-
private enableSignalsSupport?: boolean
64+
private enableSignalsSupport?: boolean,
65+
private customInjector?: Injector
6366
) {}
6467

6568
attachViewToDom(container: any, component: any, params?: any, cssClasses?: string[]): Promise<any> {
@@ -93,7 +96,8 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
9396
componentProps,
9497
cssClasses,
9598
this.elementReferenceKey,
96-
this.enableSignalsSupport
99+
this.enableSignalsSupport,
100+
this.customInjector
97101
);
98102
resolve(el);
99103
});
@@ -131,7 +135,8 @@ export const attachView = (
131135
params: any,
132136
cssClasses: string[] | undefined,
133137
elementReferenceKey: string | undefined,
134-
enableSignalsSupport: boolean | undefined
138+
enableSignalsSupport: boolean | undefined,
139+
customInjector?: Injector
135140
): any => {
136141
/**
137142
* Wraps the injector with a custom injector that
@@ -158,7 +163,7 @@ export const attachView = (
158163

159164
const childInjector = Injector.create({
160165
providers,
161-
parent: injector,
166+
parent: customInjector ?? injector,
162167
});
163168

164169
const componentRef = createComponent<any>(component, {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { Injector } from '@angular/core';
2+
import type { ModalOptions as CoreModalOptions, PopoverOptions as CorePopoverOptions } from '@ionic/core/components';
3+
4+
/**
5+
* Modal options with Angular-specific injector support.
6+
* Extends @ionic/core ModalOptions with an optional injector property.
7+
*/
8+
export type ModalOptions = CoreModalOptions & {
9+
injector?: Injector;
10+
};
11+
12+
/**
13+
* Popover options with Angular-specific injector support.
14+
* Extends @ionic/core PopoverOptions with an optional injector property.
15+
*/
16+
export type PopoverOptions = CorePopoverOptions & {
17+
injector?: Injector;
18+
};

packages/angular/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export {
3232
ViewDidEnter,
3333
ViewDidLeave,
3434
} from '@ionic/angular/common';
35+
export type { ModalOptions, PopoverOptions } from '@ionic/angular/common';
3536
export { AlertController } from './providers/alert-controller';
3637
export { AnimationController } from './providers/animation-controller';
3738
export { ActionSheetController } from './providers/action-sheet-controller';
@@ -98,14 +99,12 @@ export {
9899
IonicSafeString,
99100
LoadingOptions,
100101
MenuCustomEvent,
101-
ModalOptions,
102102
NavCustomEvent,
103103
PickerOptions,
104104
PickerButton,
105105
PickerColumn,
106106
PickerColumnOption,
107107
PlatformConfig,
108-
PopoverOptions,
109108
RadioGroupCustomEvent,
110109
RadioGroupChangeEventDetail,
111110
RangeCustomEvent,

packages/angular/src/providers/modal-controller.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Injector, Injectable, EnvironmentInjector, inject } from '@angular/core';
22
import { AngularDelegate, OverlayBaseController } from '@ionic/angular/common';
3-
import type { ModalOptions } from '@ionic/core';
3+
import type { ModalOptions } from '@ionic/angular/common';
44
import { modalController } from '@ionic/core';
55

66
@Injectable()
@@ -14,9 +14,10 @@ export class ModalController extends OverlayBaseController<ModalOptions, HTMLIon
1414
}
1515

1616
create(opts: ModalOptions): Promise<HTMLIonModalElement> {
17+
const { injector: customInjector, ...restOpts } = opts;
1718
return super.create({
18-
...opts,
19-
delegate: this.angularDelegate.create(this.environmentInjector, this.injector, 'modal'),
19+
...restOpts,
20+
delegate: this.angularDelegate.create(this.environmentInjector, this.injector, 'modal', customInjector),
2021
});
2122
}
2223
}

packages/angular/src/providers/popover-controller.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Injector, inject, EnvironmentInjector } from '@angular/core';
22
import { AngularDelegate, OverlayBaseController } from '@ionic/angular/common';
3-
import type { PopoverOptions } from '@ionic/core';
3+
import type { PopoverOptions } from '@ionic/angular/common';
44
import { popoverController } from '@ionic/core';
55

66
export class PopoverController extends OverlayBaseController<PopoverOptions, HTMLIonPopoverElement> {
@@ -13,9 +13,10 @@ export class PopoverController extends OverlayBaseController<PopoverOptions, HTM
1313
}
1414

1515
create(opts: PopoverOptions): Promise<HTMLIonPopoverElement> {
16+
const { injector: customInjector, ...restOpts } = opts;
1617
return super.create({
17-
...opts,
18-
delegate: this.angularDelegate.create(this.environmentInjector, this.injector, 'popover'),
18+
...restOpts,
19+
delegate: this.angularDelegate.create(this.environmentInjector, this.injector, 'popover', customInjector),
1920
});
2021
}
2122
}

0 commit comments

Comments
 (0)