@ionic/core 7.6.6-nightly.20240118 → 7.6.6-nightly.20240119

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -689,22 +689,41 @@ const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLEle
689
689
  const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
690
690
  const bodyIsVisible = el.classList.contains('datetime-ready');
691
691
  const { isGridStyle, showMonthAndYear } = this;
692
- if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
693
- this.animateToDate(targetValue);
692
+ let areAllSelectedDatesInSameMonth = true;
693
+ if (Array.isArray(valueToProcess)) {
694
+ const firstMonth = valueToProcess[0].month;
695
+ for (const date of valueToProcess) {
696
+ if (date.month !== firstMonth) {
697
+ areAllSelectedDatesInSameMonth = false;
698
+ break;
699
+ }
700
+ }
694
701
  }
695
- else {
696
- /**
697
- * We only need to do this if we didn't just animate to a new month,
698
- * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
699
- */
700
- this.setWorkingParts({
701
- month,
702
- day,
703
- year,
704
- hour,
705
- minute,
706
- ampm,
707
- });
702
+ /**
703
+ * If there is more than one date selected
704
+ * and the dates aren't all in the same month,
705
+ * then we should neither animate to the date
706
+ * nor update the working parts because we do
707
+ * not know which date the user wants to view.
708
+ */
709
+ if (areAllSelectedDatesInSameMonth) {
710
+ if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
711
+ this.animateToDate(targetValue);
712
+ }
713
+ else {
714
+ /**
715
+ * We only need to do this if we didn't just animate to a new month,
716
+ * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
717
+ */
718
+ this.setWorkingParts({
719
+ month,
720
+ day,
721
+ year,
722
+ hour,
723
+ minute,
724
+ ampm,
725
+ });
726
+ }
708
727
  }
709
728
  };
710
729
  this.animateToDate = async (targetValue) => {
@@ -222,6 +222,7 @@ const PickerInternal = /*@__PURE__*/ proxyCustomElement(class PickerInternal ext
222
222
  inputEl.focus();
223
223
  }
224
224
  else {
225
+ // TODO FW-5900 Use keydown instead
225
226
  el.addEventListener('keypress', this.onKeyPress);
226
227
  this.destroyKeypressListener = () => {
227
228
  el.removeEventListener('keypress', this.onKeyPress);
@@ -472,7 +473,22 @@ const PickerInternal = /*@__PURE__*/ proxyCustomElement(class PickerInternal ext
472
473
  this.emitInputModeChange();
473
474
  }
474
475
  render() {
475
- return (h(Host, { onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, h("input", { "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), h("div", { class: "picker-before" }), h("div", { class: "picker-after" }), h("div", { class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), h("slot", null)));
476
+ return (h(Host, { onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, h("input", { "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", onKeyDown: (ev) => {
477
+ var _a;
478
+ /**
479
+ * The "Enter" key represents
480
+ * the user submitting their time
481
+ * selection, so we should blur the
482
+ * input (and therefore close the keyboard)
483
+ *
484
+ * Updating the picker's state to no longer
485
+ * be in input mode is handled in the onBlur
486
+ * callback below.
487
+ */
488
+ if (ev.key === 'Enter') {
489
+ (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.blur();
490
+ }
491
+ }, ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), h("div", { class: "picker-before" }), h("div", { class: "picker-after" }), h("div", { class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), h("slot", null)));
476
492
  }
477
493
  get el() { return this; }
478
494
  static get style() { return {
@@ -688,22 +688,41 @@ const Datetime = class {
688
688
  const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
689
689
  const bodyIsVisible = el.classList.contains('datetime-ready');
690
690
  const { isGridStyle, showMonthAndYear } = this;
691
- if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
692
- this.animateToDate(targetValue);
691
+ let areAllSelectedDatesInSameMonth = true;
692
+ if (Array.isArray(valueToProcess)) {
693
+ const firstMonth = valueToProcess[0].month;
694
+ for (const date of valueToProcess) {
695
+ if (date.month !== firstMonth) {
696
+ areAllSelectedDatesInSameMonth = false;
697
+ break;
698
+ }
699
+ }
693
700
  }
694
- else {
695
- /**
696
- * We only need to do this if we didn't just animate to a new month,
697
- * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
698
- */
699
- this.setWorkingParts({
700
- month,
701
- day,
702
- year,
703
- hour,
704
- minute,
705
- ampm,
706
- });
701
+ /**
702
+ * If there is more than one date selected
703
+ * and the dates aren't all in the same month,
704
+ * then we should neither animate to the date
705
+ * nor update the working parts because we do
706
+ * not know which date the user wants to view.
707
+ */
708
+ if (areAllSelectedDatesInSameMonth) {
709
+ if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
710
+ this.animateToDate(targetValue);
711
+ }
712
+ else {
713
+ /**
714
+ * We only need to do this if we didn't just animate to a new month,
715
+ * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
716
+ */
717
+ this.setWorkingParts({
718
+ month,
719
+ day,
720
+ year,
721
+ hour,
722
+ minute,
723
+ ampm,
724
+ });
725
+ }
707
726
  }
708
727
  };
709
728
  this.animateToDate = async (targetValue) => {
@@ -224,6 +224,7 @@ const PickerInternal = class {
224
224
  inputEl.focus();
225
225
  }
226
226
  else {
227
+ // TODO FW-5900 Use keydown instead
227
228
  el.addEventListener('keypress', this.onKeyPress);
228
229
  this.destroyKeypressListener = () => {
229
230
  el.removeEventListener('keypress', this.onKeyPress);
@@ -474,7 +475,22 @@ const PickerInternal = class {
474
475
  this.emitInputModeChange();
475
476
  }
476
477
  render() {
477
- return (index.h(index.Host, { onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, index.h("input", { "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), index.h("div", { class: "picker-before" }), index.h("div", { class: "picker-after" }), index.h("div", { class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), index.h("slot", null)));
478
+ return (index.h(index.Host, { onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, index.h("input", { "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", onKeyDown: (ev) => {
479
+ var _a;
480
+ /**
481
+ * The "Enter" key represents
482
+ * the user submitting their time
483
+ * selection, so we should blur the
484
+ * input (and therefore close the keyboard)
485
+ *
486
+ * Updating the picker's state to no longer
487
+ * be in input mode is handled in the onBlur
488
+ * callback below.
489
+ */
490
+ if (ev.key === 'Enter') {
491
+ (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.blur();
492
+ }
493
+ }, ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), index.h("div", { class: "picker-before" }), index.h("div", { class: "picker-after" }), index.h("div", { class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), index.h("slot", null)));
478
494
  }
479
495
  get el() { return index.getElement(this); }
480
496
  };
@@ -526,22 +526,41 @@ export class Datetime {
526
526
  const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
527
527
  const bodyIsVisible = el.classList.contains('datetime-ready');
528
528
  const { isGridStyle, showMonthAndYear } = this;
529
- if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
530
- this.animateToDate(targetValue);
529
+ let areAllSelectedDatesInSameMonth = true;
530
+ if (Array.isArray(valueToProcess)) {
531
+ const firstMonth = valueToProcess[0].month;
532
+ for (const date of valueToProcess) {
533
+ if (date.month !== firstMonth) {
534
+ areAllSelectedDatesInSameMonth = false;
535
+ break;
536
+ }
537
+ }
531
538
  }
532
- else {
533
- /**
534
- * We only need to do this if we didn't just animate to a new month,
535
- * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
536
- */
537
- this.setWorkingParts({
538
- month,
539
- day,
540
- year,
541
- hour,
542
- minute,
543
- ampm,
544
- });
539
+ /**
540
+ * If there is more than one date selected
541
+ * and the dates aren't all in the same month,
542
+ * then we should neither animate to the date
543
+ * nor update the working parts because we do
544
+ * not know which date the user wants to view.
545
+ */
546
+ if (areAllSelectedDatesInSameMonth) {
547
+ if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
548
+ this.animateToDate(targetValue);
549
+ }
550
+ else {
551
+ /**
552
+ * We only need to do this if we didn't just animate to a new month,
553
+ * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
554
+ */
555
+ this.setWorkingParts({
556
+ month,
557
+ day,
558
+ year,
559
+ hour,
560
+ minute,
561
+ ampm,
562
+ });
563
+ }
545
564
  }
546
565
  };
547
566
  this.animateToDate = async (targetValue) => {
@@ -5,7 +5,7 @@ import { expect } from "@playwright/test";
5
5
  import { configs, test } from "../../../../utils/test/playwright/index";
6
6
  const SINGLE_DATE = '2022-06-01';
7
7
  const MULTIPLE_DATES = ['2022-06-01', '2022-06-02', '2022-06-03'];
8
- const MULTIPLE_DATES_SEPARATE_MONTHS = ['2022-04-01', '2022-05-01', '2022-06-01'];
8
+ const MULTIPLE_DATES_SEPARATE_MONTHS = ['2022-03-01', '2022-04-01', '2022-05-01'];
9
9
  class DatetimeMultipleFixture {
10
10
  constructor(page) {
11
11
  this.page = page;
@@ -118,10 +118,27 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
118
118
  value: ['2022-06-01', '2022-06-02'],
119
119
  });
120
120
  });
121
- test('multiple default values across months should display at least one value', async () => {
121
+ test('should scroll to new month when value is updated with multiple dates in the same month', async ({ page }) => {
122
+ test.info().annotations.push({
123
+ type: 'issue',
124
+ description: 'https://github.com/ionic-team/ionic-framework/issues/28602',
125
+ });
122
126
  const datetime = await datetimeFixture.goto(config, MULTIPLE_DATES_SEPARATE_MONTHS);
127
+ await datetime.evaluate((el, dates) => {
128
+ el.value = dates;
129
+ }, MULTIPLE_DATES);
130
+ await page.waitForChanges();
131
+ const monthYear = datetime.locator('.calendar-month-year');
132
+ await expect(monthYear).toHaveText(/June 2022/);
133
+ });
134
+ test('should not scroll to new month when value is updated with dates in different months', async ({ page }) => {
135
+ const datetime = await datetimeFixture.goto(config, MULTIPLE_DATES);
136
+ await datetime.evaluate((el, dates) => {
137
+ el.value = dates;
138
+ }, MULTIPLE_DATES_SEPARATE_MONTHS);
139
+ await page.waitForChanges();
123
140
  const monthYear = datetime.locator('.calendar-month-year');
124
- await expect(monthYear).toHaveText(/April 2022/);
141
+ await expect(monthYear).toHaveText(/June 2022/);
125
142
  });
126
143
  test('with buttons, should only update value when confirm is called', async ({ page }) => {
127
144
  const datetime = await datetimeFixture.goto(config, SINGLE_DATE, { showDefaultButtons: true });
@@ -217,6 +217,7 @@ export class PickerInternal {
217
217
  inputEl.focus();
218
218
  }
219
219
  else {
220
+ // TODO FW-5900 Use keydown instead
220
221
  el.addEventListener('keypress', this.onKeyPress);
221
222
  this.destroyKeypressListener = () => {
222
223
  el.removeEventListener('keypress', this.onKeyPress);
@@ -467,7 +468,22 @@ export class PickerInternal {
467
468
  this.emitInputModeChange();
468
469
  }
469
470
  render() {
470
- return (h(Host, { onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, h("input", { "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), h("div", { class: "picker-before" }), h("div", { class: "picker-after" }), h("div", { class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), h("slot", null)));
471
+ return (h(Host, { onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, h("input", { "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", onKeyDown: (ev) => {
472
+ var _a;
473
+ /**
474
+ * The "Enter" key represents
475
+ * the user submitting their time
476
+ * selection, so we should blur the
477
+ * input (and therefore close the keyboard)
478
+ *
479
+ * Updating the picker's state to no longer
480
+ * be in input mode is handled in the onBlur
481
+ * callback below.
482
+ */
483
+ if (ev.key === 'Enter') {
484
+ (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.blur();
485
+ }
486
+ }, ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), h("div", { class: "picker-before" }), h("div", { class: "picker-after" }), h("div", { class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), h("slot", null)));
471
487
  }
472
488
  static get is() { return "ion-picker-internal"; }
473
489
  static get encapsulation() { return "shadow"; }
@@ -110,5 +110,37 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
110
110
  await expect(ionChange).toHaveReceivedEventDetail({ text: '00', value: 12 });
111
111
  await expect(column).toHaveJSProperty('value', 12);
112
112
  });
113
+ test('pressing Enter should dismiss the keyboard', async ({ page }) => {
114
+ test.info().annotations.push({
115
+ type: 'issue',
116
+ description: 'https://github.com/ionic-team/ionic-framework/issues/28325',
117
+ });
118
+ await page.setContent(`
119
+ <ion-picker-internal>
120
+ <ion-picker-column-internal></ion-picker-column-internal>
121
+ </ion-picker-internal>
122
+
123
+ <script>
124
+ const column = document.querySelector('ion-picker-column-internal');
125
+ column.items = [
126
+ { text: '00', value: 12 },
127
+ { text: '01', value: 1 },
128
+ { text: '02', value: 2 },
129
+ { text: '03', value: 3 },
130
+ { text: '04', value: 4 },
131
+ { text: '05', value: 5 }
132
+ ];
133
+ column.value = 5;
134
+ column.numericInput = true;
135
+ </script>
136
+ `, config);
137
+ const column = page.locator('ion-picker-column-internal');
138
+ await column.click();
139
+ const input = page.locator('ion-picker-internal input');
140
+ await expect(input).toBeFocused();
141
+ // pressing Enter should blur the input and therefore close the keyboard
142
+ await page.keyboard.press('Enter');
143
+ await expect(input).not.toBeFocused();
144
+ });
113
145
  });
114
146
  });
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2024-01-18T06:07:58",
2
+ "timestamp": "2024-01-19T06:07:38",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.10.0",
@@ -684,22 +684,41 @@ const Datetime = class {
684
684
  const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
685
685
  const bodyIsVisible = el.classList.contains('datetime-ready');
686
686
  const { isGridStyle, showMonthAndYear } = this;
687
- if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
688
- this.animateToDate(targetValue);
687
+ let areAllSelectedDatesInSameMonth = true;
688
+ if (Array.isArray(valueToProcess)) {
689
+ const firstMonth = valueToProcess[0].month;
690
+ for (const date of valueToProcess) {
691
+ if (date.month !== firstMonth) {
692
+ areAllSelectedDatesInSameMonth = false;
693
+ break;
694
+ }
695
+ }
689
696
  }
690
- else {
691
- /**
692
- * We only need to do this if we didn't just animate to a new month,
693
- * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
694
- */
695
- this.setWorkingParts({
696
- month,
697
- day,
698
- year,
699
- hour,
700
- minute,
701
- ampm,
702
- });
697
+ /**
698
+ * If there is more than one date selected
699
+ * and the dates aren't all in the same month,
700
+ * then we should neither animate to the date
701
+ * nor update the working parts because we do
702
+ * not know which date the user wants to view.
703
+ */
704
+ if (areAllSelectedDatesInSameMonth) {
705
+ if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
706
+ this.animateToDate(targetValue);
707
+ }
708
+ else {
709
+ /**
710
+ * We only need to do this if we didn't just animate to a new month,
711
+ * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
712
+ */
713
+ this.setWorkingParts({
714
+ month,
715
+ day,
716
+ year,
717
+ hour,
718
+ minute,
719
+ ampm,
720
+ });
721
+ }
703
722
  }
704
723
  };
705
724
  this.animateToDate = async (targetValue) => {
@@ -220,6 +220,7 @@ const PickerInternal = class {
220
220
  inputEl.focus();
221
221
  }
222
222
  else {
223
+ // TODO FW-5900 Use keydown instead
223
224
  el.addEventListener('keypress', this.onKeyPress);
224
225
  this.destroyKeypressListener = () => {
225
226
  el.removeEventListener('keypress', this.onKeyPress);
@@ -470,7 +471,22 @@ const PickerInternal = class {
470
471
  this.emitInputModeChange();
471
472
  }
472
473
  render() {
473
- return (h(Host, { onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, h("input", { "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), h("div", { class: "picker-before" }), h("div", { class: "picker-after" }), h("div", { class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), h("slot", null)));
474
+ return (h(Host, { onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, h("input", { "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", onKeyDown: (ev) => {
475
+ var _a;
476
+ /**
477
+ * The "Enter" key represents
478
+ * the user submitting their time
479
+ * selection, so we should blur the
480
+ * input (and therefore close the keyboard)
481
+ *
482
+ * Updating the picker's state to no longer
483
+ * be in input mode is handled in the onBlur
484
+ * callback below.
485
+ */
486
+ if (ev.key === 'Enter') {
487
+ (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.blur();
488
+ }
489
+ }, ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), h("div", { class: "picker-before" }), h("div", { class: "picker-after" }), h("div", { class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), h("slot", null)));
474
490
  }
475
491
  get el() { return getElement(this); }
476
492
  };