@ionic/core 7.7.5 → 7.8.0

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.
Files changed (60) hide show
  1. package/components/data.js +23 -38
  2. package/components/ion-datetime-button.js +11 -10
  3. package/components/ion-datetime.js +69 -7
  4. package/components/ion-searchbar.js +34 -5
  5. package/dist/cjs/{data-a5109f09.js → data-4487a815.js} +22 -39
  6. package/dist/cjs/ion-datetime-button.cjs.entry.js +11 -10
  7. package/dist/cjs/ion-datetime_3.cjs.entry.js +66 -7
  8. package/dist/cjs/ion-searchbar.cjs.entry.js +28 -4
  9. package/dist/cjs/ionic.cjs.js +1 -1
  10. package/dist/cjs/loader.cjs.js +1 -1
  11. package/dist/collection/components/datetime/datetime.js +50 -7
  12. package/dist/collection/components/datetime/test/basic/datetime.e2e.js +77 -0
  13. package/dist/collection/components/datetime/test/format.spec.js +65 -15
  14. package/dist/collection/components/datetime/utils/format.js +24 -37
  15. package/dist/collection/components/datetime/utils/validate.js +45 -0
  16. package/dist/collection/components/datetime-button/datetime-button.js +11 -10
  17. package/dist/collection/components/datetime-button/test/basic/datetime-button.e2e.js +65 -0
  18. package/dist/collection/components/searchbar/searchbar.js +84 -5
  19. package/dist/collection/components/searchbar/test/searchbar.spec.js +20 -2
  20. package/dist/docs.json +113 -1
  21. package/dist/esm/{data-0f3ab200.js → data-bb424ba8.js} +23 -38
  22. package/dist/esm/ion-datetime-button.entry.js +11 -10
  23. package/dist/esm/ion-datetime_3.entry.js +66 -7
  24. package/dist/esm/ion-searchbar.entry.js +29 -5
  25. package/dist/esm/ionic.js +1 -1
  26. package/dist/esm/loader.js +1 -1
  27. package/dist/esm-es5/data-bb424ba8.js +4 -0
  28. package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
  29. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  30. package/dist/esm-es5/ion-searchbar.entry.js +1 -1
  31. package/dist/esm-es5/ionic.js +1 -1
  32. package/dist/esm-es5/loader.js +1 -1
  33. package/dist/html.html-data.json +12 -0
  34. package/dist/ionic/ionic.esm.js +1 -1
  35. package/dist/ionic/p-2b77099e.system.entry.js +4 -0
  36. package/dist/ionic/p-3789920e.js +4 -0
  37. package/dist/ionic/p-4abb3f9e.entry.js +4 -0
  38. package/dist/ionic/p-60c9fd9e.system.js +1 -1
  39. package/dist/ionic/p-8a1b0abb.system.js +4 -0
  40. package/dist/ionic/p-a722d78f.system.entry.js +4 -0
  41. package/dist/ionic/p-bc56a728.entry.js +4 -0
  42. package/dist/ionic/p-cfd31f45.system.entry.js +4 -0
  43. package/dist/ionic/p-e02681a6.entry.js +4 -0
  44. package/dist/types/components/datetime/datetime-interface.d.ts +10 -0
  45. package/dist/types/components/datetime/datetime.d.ts +9 -1
  46. package/dist/types/components/datetime/utils/format.d.ts +7 -13
  47. package/dist/types/components/datetime/utils/validate.d.ts +8 -0
  48. package/dist/types/components/searchbar/searchbar.d.ts +38 -0
  49. package/dist/types/components.d.ts +34 -2
  50. package/hydrate/index.js +127 -56
  51. package/package.json +1 -1
  52. package/dist/esm-es5/data-0f3ab200.js +0 -4
  53. package/dist/ionic/p-6f5b32c7.system.entry.js +0 -4
  54. package/dist/ionic/p-7330c044.system.js +0 -4
  55. package/dist/ionic/p-76afa95f.entry.js +0 -4
  56. package/dist/ionic/p-81f18ed1.system.entry.js +0 -4
  57. package/dist/ionic/p-c67c9644.entry.js +0 -4
  58. package/dist/ionic/p-e447e552.entry.js +0 -4
  59. package/dist/ionic/p-ef269a56.system.entry.js +0 -4
  60. package/dist/ionic/p-f7dce541.js +0 -4
@@ -0,0 +1,45 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { printIonWarning } from "../../../utils/logging/index";
5
+ /**
6
+ * If a time zone is provided in the format options, the rendered text could
7
+ * differ from what was selected in the Datetime, which could cause
8
+ * confusion.
9
+ */
10
+ export const warnIfTimeZoneProvided = (el, formatOptions) => {
11
+ var _a, _b, _c, _d;
12
+ if (((_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) === null || _a === void 0 ? void 0 : _a.timeZone) ||
13
+ ((_b = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) === null || _b === void 0 ? void 0 : _b.timeZoneName) ||
14
+ ((_c = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) === null || _c === void 0 ? void 0 : _c.timeZone) ||
15
+ ((_d = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) === null || _d === void 0 ? void 0 : _d.timeZoneName)) {
16
+ printIonWarning('Datetime: "timeZone" and "timeZoneName" are not supported in "formatOptions".', el);
17
+ }
18
+ };
19
+ export const checkForPresentationFormatMismatch = (el, presentation, formatOptions) => {
20
+ // formatOptions is not required
21
+ if (!formatOptions)
22
+ return;
23
+ // If formatOptions is provided, the date and/or time objects are required, depending on the presentation
24
+ switch (presentation) {
25
+ case 'date':
26
+ case 'month-year':
27
+ case 'month':
28
+ case 'year':
29
+ if (formatOptions.date === undefined) {
30
+ printIonWarning(`Datetime: The '${presentation}' presentation requires a date object in formatOptions.`, el);
31
+ }
32
+ break;
33
+ case 'time':
34
+ if (formatOptions.time === undefined) {
35
+ printIonWarning(`Datetime: The 'time' presentation requires a time object in formatOptions.`, el);
36
+ }
37
+ break;
38
+ case 'date-time':
39
+ case 'time-date':
40
+ if (formatOptions.date === undefined && formatOptions.time === undefined) {
41
+ printIonWarning(`Datetime: The '${presentation}' presentation requires either a date or time object (or both) in formatOptions.`, el);
42
+ }
43
+ break;
44
+ }
45
+ };
@@ -7,7 +7,7 @@ import { printIonError } from "../../utils/logging/index";
7
7
  import { createColorClasses } from "../../utils/theme";
8
8
  import { getIonMode } from "../../global/ionic-global";
9
9
  import { getToday } from "../datetime/utils/data";
10
- import { getMonthAndYear, getMonthDayAndYear, getLocalizedDateTime, getLocalizedTime } from "../datetime/utils/format";
10
+ import { getLocalizedDateTime, getLocalizedTime } from "../datetime/utils/format";
11
11
  import { getHourCycle } from "../datetime/utils/helpers";
12
12
  import { parseDate } from "../datetime/utils/parse";
13
13
  /**
@@ -43,11 +43,12 @@ export class DatetimeButton {
43
43
  * to the locale specified on ion-datetime.
44
44
  */
45
45
  this.setDateTimeText = () => {
46
+ var _a, _b, _c, _d, _e;
46
47
  const { datetimeEl, datetimePresentation } = this;
47
48
  if (!datetimeEl) {
48
49
  return;
49
50
  }
50
- const { value, locale, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
51
+ const { value, locale, formatOptions, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
51
52
  const parsedValues = this.getParsedDateValues(value);
52
53
  /**
53
54
  * Both ion-datetime and ion-datetime-button default
@@ -70,8 +71,8 @@ export class DatetimeButton {
70
71
  switch (datetimePresentation) {
71
72
  case 'date-time':
72
73
  case 'time-date':
73
- const dateText = getMonthDayAndYear(locale, firstParsedDatetime);
74
- const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
74
+ const dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _a !== void 0 ? _a : { month: 'short', day: 'numeric', year: 'numeric' });
75
+ const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time);
75
76
  if (preferWheel) {
76
77
  this.dateText = `${dateText} ${timeText}`;
77
78
  }
@@ -94,20 +95,20 @@ export class DatetimeButton {
94
95
  this.dateText = headerText;
95
96
  }
96
97
  else {
97
- this.dateText = getMonthDayAndYear(locale, firstParsedDatetime);
98
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_b = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _b !== void 0 ? _b : { month: 'short', day: 'numeric', year: 'numeric' });
98
99
  }
99
100
  break;
100
101
  case 'time':
101
- this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
102
+ this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time);
102
103
  break;
103
104
  case 'month-year':
104
- this.dateText = getMonthAndYear(locale, firstParsedDatetime);
105
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_c = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _c !== void 0 ? _c : { month: 'long', year: 'numeric' });
105
106
  break;
106
107
  case 'month':
107
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, { month: 'long' });
108
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_d = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _d !== void 0 ? _d : { month: 'long' });
108
109
  break;
109
110
  case 'year':
110
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, { year: 'numeric' });
111
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_e = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _e !== void 0 ? _e : { year: 'numeric' });
111
112
  break;
112
113
  }
113
114
  };
@@ -336,7 +337,7 @@ export class DatetimeButton {
336
337
  render() {
337
338
  const { color, dateText, timeText, selectedButton, datetimeActive, disabled } = this;
338
339
  const mode = getIonMode(this);
339
- return (h(Host, { key: '36fe34d4225940611d74bdef5b954d54749d2dca', class: createColorClasses(color, {
340
+ return (h(Host, { key: '861a08f4a239de771875aee9b505e06ac7064b32', class: createColorClasses(color, {
340
341
  [mode]: true,
341
342
  [`${selectedButton}-active`]: datetimeActive,
342
343
  ['datetime-button-disabled']: disabled,
@@ -174,4 +174,69 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
174
174
  await expect(page.locator('#time-button')).not.toBeVisible();
175
175
  });
176
176
  });
177
+ test.describe(title('datetime-button: formatOptions'), () => {
178
+ test('should include date and time for presentation date-time', async ({ page }) => {
179
+ await page.setContent(`
180
+ <ion-datetime-button datetime="datetime"></ion-datetime-button>
181
+ <ion-datetime id="datetime" presentation="date-time" value="2023-11-02T01:22:00" locale="en-US"></ion-datetime>
182
+ <script>
183
+ const datetime = document.querySelector('ion-datetime');
184
+ datetime.formatOptions = {
185
+ date: {
186
+ weekday: "short",
187
+ month: "long",
188
+ day: "2-digit"
189
+ },
190
+ time: {
191
+ hour: "2-digit",
192
+ minute: "2-digit"
193
+ }
194
+ }
195
+ </script>
196
+ `, config);
197
+ await page.locator('.datetime-ready').waitFor();
198
+ await expect(page.locator('#date-button')).toContainText('Thu, November 02');
199
+ await expect(page.locator('#time-button')).toContainText('01:22 AM');
200
+ });
201
+ test('should include date for presentation date', async ({ page }) => {
202
+ await page.setContent(`
203
+ <ion-datetime-button datetime="datetime"></ion-datetime-button>
204
+ <ion-datetime id="datetime" presentation="date" value="2023-11-02" locale="en-US"></ion-datetime>
205
+ <script>
206
+ const datetime = document.querySelector('ion-datetime');
207
+ datetime.formatOptions = {
208
+ date: {
209
+ weekday: "short",
210
+ month: "long",
211
+ day: "2-digit"
212
+ }
213
+ }
214
+ </script>
215
+ `, config);
216
+ await page.locator('.datetime-ready').waitFor();
217
+ await expect(page.locator('#date-button')).toContainText('Thu, November 02');
218
+ });
219
+ test('should include date and time in same button for preferWheel', async ({ page }) => {
220
+ await page.setContent(`
221
+ <ion-datetime-button datetime="datetime"></ion-datetime-button>
222
+ <ion-datetime id="datetime" presentation="date-time" value="2023-11-02T01:22:00" locale="en-US" prefer-wheel="true"></ion-datetime>
223
+ <script>
224
+ const datetime = document.querySelector('ion-datetime');
225
+ datetime.formatOptions = {
226
+ date: {
227
+ weekday: "short",
228
+ month: "long",
229
+ day: "2-digit"
230
+ },
231
+ time: {
232
+ hour: "2-digit",
233
+ minute: "2-digit"
234
+ }
235
+ }
236
+ </script>
237
+ `, config);
238
+ await page.locator('.datetime-ready').waitFor();
239
+ await expect(page.locator('ion-datetime-button')).toContainText('Thu, November 02 01:22 AM');
240
+ });
241
+ });
177
242
  });
@@ -2,7 +2,7 @@
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
4
  import { Host, forceUpdate, h } from "@stencil/core";
5
- import { debounceEvent, raf, componentOnReady } from "../../utils/helpers";
5
+ import { debounceEvent, raf, componentOnReady, inheritAttributes } from "../../utils/helpers";
6
6
  import { isRTL } from "../../utils/rtl/index";
7
7
  import { createColorClasses } from "../../utils/theme";
8
8
  import { arrowBackSharp, closeCircle, closeSharp, searchOutline, searchSharp } from "ionicons/icons";
@@ -16,6 +16,7 @@ export class Searchbar {
16
16
  this.isCancelVisible = false;
17
17
  this.shouldAlignLeft = true;
18
18
  this.inputId = `ion-searchbar-${searchbarIds++}`;
19
+ this.inheritedAttributes = {};
19
20
  /**
20
21
  * Clears the input field and triggers the control change.
21
22
  */
@@ -116,6 +117,7 @@ export class Searchbar {
116
117
  this.noAnimate = true;
117
118
  this.color = undefined;
118
119
  this.animated = false;
120
+ this.autocapitalize = undefined;
119
121
  this.autocomplete = 'off';
120
122
  this.autocorrect = 'off';
121
123
  this.cancelButtonIcon = config.get('backButtonIcon', arrowBackSharp);
@@ -125,6 +127,8 @@ export class Searchbar {
125
127
  this.disabled = false;
126
128
  this.inputmode = undefined;
127
129
  this.enterkeyhint = undefined;
130
+ this.maxlength = undefined;
131
+ this.minlength = undefined;
128
132
  this.name = this.inputId;
129
133
  this.placeholder = 'Search';
130
134
  this.searchIcon = undefined;
@@ -134,6 +138,21 @@ export class Searchbar {
134
138
  this.type = 'search';
135
139
  this.value = '';
136
140
  }
141
+ /**
142
+ * lang and dir are globally enumerated attributes.
143
+ * As a result, creating these as properties
144
+ * can have unintended side effects. Instead, we
145
+ * listen for attribute changes and inherit them
146
+ * to the inner `<input>` element.
147
+ */
148
+ onLangChanged(newValue) {
149
+ this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { lang: newValue });
150
+ forceUpdate(this);
151
+ }
152
+ onDirChanged(newValue) {
153
+ this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { dir: newValue });
154
+ forceUpdate(this);
155
+ }
137
156
  debounceChanged() {
138
157
  const { ionInput, debounce, originalIonInput } = this;
139
158
  /**
@@ -158,6 +177,9 @@ export class Searchbar {
158
177
  connectedCallback() {
159
178
  this.emitStyle();
160
179
  }
180
+ componentWillLoad() {
181
+ this.inheritedAttributes = Object.assign({}, inheritAttributes(this.el, ['lang', 'dir']));
182
+ }
161
183
  componentDidLoad() {
162
184
  this.originalIonInput = this.ionInput;
163
185
  this.positionElements();
@@ -356,8 +378,8 @@ export class Searchbar {
356
378
  const clearIcon = this.clearIcon || (mode === 'ios' ? closeCircle : closeSharp);
357
379
  const searchIcon = this.searchIcon || (mode === 'ios' ? searchOutline : searchSharp);
358
380
  const shouldShowCancelButton = this.shouldShowCancelButton();
359
- const cancelButton = this.showCancelButton !== 'never' && (h("button", { key: '1de9b9bc6bad708bafcf4d31fa82838355120486', "aria-label": cancelButtonText, "aria-hidden": shouldShowCancelButton ? undefined : 'true', type: "button", tabIndex: mode === 'ios' && !shouldShowCancelButton ? -1 : undefined, onMouseDown: this.onCancelSearchbar, onTouchStart: this.onCancelSearchbar, class: "searchbar-cancel-button" }, h("div", { key: 'e5178016e17104a80732edbae73c0dfc264bfe52', "aria-hidden": "true" }, mode === 'md' ? (h("ion-icon", { "aria-hidden": "true", mode: mode, icon: this.cancelButtonIcon, lazy: false })) : (cancelButtonText))));
360
- return (h(Host, { key: '2c88a7b6ec7f33ada7dae560881210d7a8800f76', role: "search", "aria-disabled": this.disabled ? 'true' : null, class: createColorClasses(this.color, {
381
+ const cancelButton = this.showCancelButton !== 'never' && (h("button", { key: '1a68689b5c14cde6e071c4095457146b9ac2e7ab', "aria-label": cancelButtonText, "aria-hidden": shouldShowCancelButton ? undefined : 'true', type: "button", tabIndex: mode === 'ios' && !shouldShowCancelButton ? -1 : undefined, onMouseDown: this.onCancelSearchbar, onTouchStart: this.onCancelSearchbar, class: "searchbar-cancel-button" }, h("div", { key: '25ae47914baa4b7e0281efb2b296d1799a56c764', "aria-hidden": "true" }, mode === 'md' ? (h("ion-icon", { "aria-hidden": "true", mode: mode, icon: this.cancelButtonIcon, lazy: false })) : (cancelButtonText))));
382
+ return (h(Host, { key: '2cf545c40874bc4a19b6af022f5ec41b3a913495', role: "search", "aria-disabled": this.disabled ? 'true' : null, class: createColorClasses(this.color, {
361
383
  [mode]: true,
362
384
  'searchbar-animated': animated,
363
385
  'searchbar-disabled': this.disabled,
@@ -367,14 +389,14 @@ export class Searchbar {
367
389
  'searchbar-has-focus': this.focused,
368
390
  'searchbar-should-show-clear': this.shouldShowClearButton(),
369
391
  'searchbar-should-show-cancel': this.shouldShowCancelButton(),
370
- }) }, h("div", { key: '8e914264a99453748a2bf370943e4047a0a587fb', class: "searchbar-input-container" }, h("input", { key: 'd772f3e8d42301e50fbd6c9deb332fbdf3c435ac', "aria-label": "search text", disabled: this.disabled, ref: (el) => (this.nativeInput = el), class: "searchbar-input", inputMode: this.inputmode, enterKeyHint: this.enterkeyhint, name: this.name, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, placeholder: this.placeholder, type: this.type, value: this.getValue(), autoComplete: this.autocomplete, autoCorrect: this.autocorrect, spellcheck: this.spellcheck }), mode === 'md' && cancelButton, h("ion-icon", { key: '8d9b461c2c34729b1bb562c227868cf817a353bc', "aria-hidden": "true", mode: mode, icon: searchIcon, lazy: false, class: "searchbar-search-icon" }), h("button", { key: 'bcc39be721f4b825af31aae4dfb3058722d889a8', "aria-label": "reset", type: "button", "no-blur": true, class: "searchbar-clear-button", onPointerDown: (ev) => {
392
+ }) }, h("div", { key: '9cf49297278839bbe6e2ef9936de337daa53c08d', class: "searchbar-input-container" }, h("input", Object.assign({ key: 'bae5db413a302e116012251746d599030f7158ce', "aria-label": "search text", disabled: this.disabled, ref: (el) => (this.nativeInput = el), class: "searchbar-input", inputMode: this.inputmode, enterKeyHint: this.enterkeyhint, name: this.name, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, minLength: this.minlength, maxLength: this.maxlength, placeholder: this.placeholder, type: this.type, value: this.getValue(), autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, spellcheck: this.spellcheck }, this.inheritedAttributes)), mode === 'md' && cancelButton, h("ion-icon", { key: '67c593ca842551d9e99e8239115cc7b43261b542', "aria-hidden": "true", mode: mode, icon: searchIcon, lazy: false, class: "searchbar-search-icon" }), h("button", { key: '6901c3f6c74cce2d3b7e46fbff85ee6e6399bdb1', "aria-label": "reset", type: "button", "no-blur": true, class: "searchbar-clear-button", onPointerDown: (ev) => {
371
393
  /**
372
394
  * This prevents mobile browsers from
373
395
  * blurring the input when the clear
374
396
  * button is activated.
375
397
  */
376
398
  ev.preventDefault();
377
- }, onClick: () => this.onClearInput(true) }, h("ion-icon", { key: '9a6478e1f1482aa6e62c88bd96cd19cacbfb8d60', "aria-hidden": "true", mode: mode, icon: clearIcon, lazy: false, class: "searchbar-clear-icon" }))), mode === 'ios' && cancelButton));
399
+ }, onClick: () => this.onClearInput(true) }, h("ion-icon", { key: 'abd45fb79ee807cf8352aa7bf5b0342f2d686227', "aria-hidden": "true", mode: mode, icon: clearIcon, lazy: false, class: "searchbar-clear-icon" }))), mode === 'ios' && cancelButton));
378
400
  }
379
401
  static get is() { return "ion-searchbar"; }
380
402
  static get encapsulation() { return "scoped"; }
@@ -433,6 +455,23 @@ export class Searchbar {
433
455
  "reflect": false,
434
456
  "defaultValue": "false"
435
457
  },
458
+ "autocapitalize": {
459
+ "type": "string",
460
+ "mutable": false,
461
+ "complexType": {
462
+ "original": "string",
463
+ "resolved": "string",
464
+ "references": {}
465
+ },
466
+ "required": true,
467
+ "optional": false,
468
+ "docs": {
469
+ "tags": [],
470
+ "text": "Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.\nAvailable options: `\"off\"`, `\"none\"`, `\"on\"`, `\"sentences\"`, `\"words\"`, `\"characters\"`."
471
+ },
472
+ "attribute": "autocapitalize",
473
+ "reflect": false
474
+ },
436
475
  "autocomplete": {
437
476
  "type": "string",
438
477
  "mutable": false,
@@ -597,6 +636,40 @@ export class Searchbar {
597
636
  "attribute": "enterkeyhint",
598
637
  "reflect": false
599
638
  },
639
+ "maxlength": {
640
+ "type": "number",
641
+ "mutable": false,
642
+ "complexType": {
643
+ "original": "number",
644
+ "resolved": "number | undefined",
645
+ "references": {}
646
+ },
647
+ "required": false,
648
+ "optional": true,
649
+ "docs": {
650
+ "tags": [],
651
+ "text": "This attribute specifies the maximum number of characters that the user can enter."
652
+ },
653
+ "attribute": "maxlength",
654
+ "reflect": false
655
+ },
656
+ "minlength": {
657
+ "type": "number",
658
+ "mutable": false,
659
+ "complexType": {
660
+ "original": "number",
661
+ "resolved": "number | undefined",
662
+ "references": {}
663
+ },
664
+ "required": false,
665
+ "optional": true,
666
+ "docs": {
667
+ "tags": [],
668
+ "text": "This attribute specifies the minimum number of characters that the user can enter."
669
+ },
670
+ "attribute": "minlength",
671
+ "reflect": false
672
+ },
600
673
  "name": {
601
674
  "type": "string",
602
675
  "mutable": false,
@@ -922,6 +995,12 @@ export class Searchbar {
922
995
  static get elementRef() { return "el"; }
923
996
  static get watchers() {
924
997
  return [{
998
+ "propName": "lang",
999
+ "methodName": "onLangChanged"
1000
+ }, {
1001
+ "propName": "dir",
1002
+ "methodName": "onDirChanged"
1003
+ }, {
925
1004
  "propName": "debounce",
926
1005
  "methodName": "debounceChanged"
927
1006
  }, {
@@ -4,12 +4,30 @@
4
4
  import { newSpecPage } from "@stencil/core/testing";
5
5
  import { Searchbar } from "../searchbar";
6
6
  describe('searchbar: rendering', () => {
7
- it('should inherit attributes', async () => {
7
+ it('should inherit properties on load', async () => {
8
8
  const page = await newSpecPage({
9
9
  components: [Searchbar],
10
- html: '<ion-searchbar name="search"></ion-searchbar>',
10
+ html: '<ion-searchbar autocapitalize="off" maxlength="4" minlength="2" name="search"></ion-searchbar>',
11
11
  });
12
12
  const nativeEl = page.body.querySelector('ion-searchbar input');
13
13
  expect(nativeEl.getAttribute('name')).toBe('search');
14
+ expect(nativeEl.getAttribute('maxlength')).toBe('4');
15
+ expect(nativeEl.getAttribute('minlength')).toBe('2');
16
+ expect(nativeEl.getAttribute('autocapitalize')).toBe('off');
17
+ });
18
+ it('should inherit watched attributes', async () => {
19
+ const page = await newSpecPage({
20
+ components: [Searchbar],
21
+ html: '<ion-searchbar dir="ltr" lang="en-US"></ion-searchbar>',
22
+ });
23
+ const searchbarEl = page.body.querySelector('ion-searchbar');
24
+ const nativeEl = searchbarEl.querySelector('input');
25
+ expect(nativeEl.getAttribute('lang')).toBe('en-US');
26
+ expect(nativeEl.getAttribute('dir')).toBe('ltr');
27
+ searchbarEl.setAttribute('lang', 'es-ES');
28
+ searchbarEl.setAttribute('dir', 'rtl');
29
+ await page.waitForChanges();
30
+ expect(nativeEl.getAttribute('lang')).toBe('es-ES');
31
+ expect(nativeEl.getAttribute('dir')).toBe('rtl');
14
32
  });
15
33
  });
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2024-03-13T13:10:59",
2
+ "timestamp": "2024-03-13T13:43:36",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.12.5",
@@ -7086,6 +7086,44 @@
7086
7086
  "optional": false,
7087
7087
  "required": false
7088
7088
  },
7089
+ {
7090
+ "name": "formatOptions",
7091
+ "type": "undefined | { date: DateTimeFormatOptions; time?: DateTimeFormatOptions | undefined; } | { date?: DateTimeFormatOptions | undefined; time: DateTimeFormatOptions; }",
7092
+ "complexType": {
7093
+ "original": "FormatOptions",
7094
+ "resolved": "undefined | { date: DateTimeFormatOptions; time?: DateTimeFormatOptions | undefined; } | { date?: DateTimeFormatOptions | undefined; time: DateTimeFormatOptions; }",
7095
+ "references": {
7096
+ "FormatOptions": {
7097
+ "location": "import",
7098
+ "path": "./datetime-interface",
7099
+ "id": "src/components/datetime/datetime-interface.ts::FormatOptions"
7100
+ }
7101
+ }
7102
+ },
7103
+ "mutable": false,
7104
+ "reflectToAttr": false,
7105
+ "docs": "Formatting options for dates and times.\nShould include a 'date' and/or 'time' object, each of which is of type [Intl.DateTimeFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options).",
7106
+ "docsTags": [],
7107
+ "values": [
7108
+ {
7109
+ "type": "undefined"
7110
+ },
7111
+ {
7112
+ "type": "{ date: DateTimeFormatOptions; time?: DateTimeFormatOptions"
7113
+ },
7114
+ {
7115
+ "type": "undefined; }"
7116
+ },
7117
+ {
7118
+ "type": "{ date?: DateTimeFormatOptions"
7119
+ },
7120
+ {
7121
+ "type": "undefined; time: DateTimeFormatOptions; }"
7122
+ }
7123
+ ],
7124
+ "optional": true,
7125
+ "required": false
7126
+ },
7089
7127
  {
7090
7128
  "name": "highlightedDates",
7091
7129
  "type": "((dateIsoString: string) => DatetimeHighlightStyle | undefined) | DatetimeHighlight[] | undefined",
@@ -22393,6 +22431,27 @@
22393
22431
  "optional": false,
22394
22432
  "required": false
22395
22433
  },
22434
+ {
22435
+ "name": "autocapitalize",
22436
+ "type": "string",
22437
+ "complexType": {
22438
+ "original": "string",
22439
+ "resolved": "string",
22440
+ "references": {}
22441
+ },
22442
+ "mutable": false,
22443
+ "attr": "autocapitalize",
22444
+ "reflectToAttr": false,
22445
+ "docs": "Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.\nAvailable options: `\"off\"`, `\"none\"`, `\"on\"`, `\"sentences\"`, `\"words\"`, `\"characters\"`.",
22446
+ "docsTags": [],
22447
+ "values": [
22448
+ {
22449
+ "type": "string"
22450
+ }
22451
+ ],
22452
+ "optional": false,
22453
+ "required": true
22454
+ },
22396
22455
  {
22397
22456
  "name": "autocomplete",
22398
22457
  "type": "\"name\" | \"email\" | \"tel\" | \"url\" | \"on\" | \"off\" | \"honorific-prefix\" | \"given-name\" | \"additional-name\" | \"family-name\" | \"honorific-suffix\" | \"nickname\" | \"username\" | \"new-password\" | \"current-password\" | \"one-time-code\" | \"organization-title\" | \"organization\" | \"street-address\" | \"address-line1\" | \"address-line2\" | \"address-line3\" | \"address-level4\" | \"address-level3\" | \"address-level2\" | \"address-level1\" | \"country\" | \"country-name\" | \"postal-code\" | \"cc-name\" | \"cc-given-name\" | \"cc-additional-name\" | \"cc-family-name\" | \"cc-number\" | \"cc-exp\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-csc\" | \"cc-type\" | \"transaction-currency\" | \"transaction-amount\" | \"language\" | \"bday\" | \"bday-day\" | \"bday-month\" | \"bday-year\" | \"sex\" | \"tel-country-code\" | \"tel-national\" | \"tel-area-code\" | \"tel-local\" | \"tel-extension\" | \"impp\" | \"photo\"",
@@ -22943,6 +23002,54 @@
22943
23002
  "optional": true,
22944
23003
  "required": false
22945
23004
  },
23005
+ {
23006
+ "name": "maxlength",
23007
+ "type": "number | undefined",
23008
+ "complexType": {
23009
+ "original": "number",
23010
+ "resolved": "number | undefined",
23011
+ "references": {}
23012
+ },
23013
+ "mutable": false,
23014
+ "attr": "maxlength",
23015
+ "reflectToAttr": false,
23016
+ "docs": "This attribute specifies the maximum number of characters that the user can enter.",
23017
+ "docsTags": [],
23018
+ "values": [
23019
+ {
23020
+ "type": "number"
23021
+ },
23022
+ {
23023
+ "type": "undefined"
23024
+ }
23025
+ ],
23026
+ "optional": true,
23027
+ "required": false
23028
+ },
23029
+ {
23030
+ "name": "minlength",
23031
+ "type": "number | undefined",
23032
+ "complexType": {
23033
+ "original": "number",
23034
+ "resolved": "number | undefined",
23035
+ "references": {}
23036
+ },
23037
+ "mutable": false,
23038
+ "attr": "minlength",
23039
+ "reflectToAttr": false,
23040
+ "docs": "This attribute specifies the minimum number of characters that the user can enter.",
23041
+ "docsTags": [],
23042
+ "values": [
23043
+ {
23044
+ "type": "number"
23045
+ },
23046
+ {
23047
+ "type": "undefined"
23048
+ }
23049
+ ],
23050
+ "optional": true,
23051
+ "required": false
23052
+ },
22946
23053
  {
22947
23054
  "name": "mode",
22948
23055
  "type": "\"ios\" | \"md\"",
@@ -29369,6 +29476,11 @@
29369
29476
  "docstring": "",
29370
29477
  "path": "src/components/content/content-interface.ts"
29371
29478
  },
29479
+ "src/components/datetime/datetime-interface.ts::FormatOptions": {
29480
+ "declaration": "export type FormatOptions =\n | {\n date: Intl.DateTimeFormatOptions;\n time?: Intl.DateTimeFormatOptions;\n }\n | {\n date?: Intl.DateTimeFormatOptions;\n time: Intl.DateTimeFormatOptions;\n };",
29481
+ "docstring": "",
29482
+ "path": "src/components/datetime/datetime-interface.ts"
29483
+ },
29372
29484
  "src/components/datetime/datetime-interface.ts::DatetimePresentation": {
29373
29485
  "declaration": "export type DatetimePresentation = 'date-time' | 'time-date' | 'date' | 'time' | 'month' | 'year' | 'month-year';",
29374
29486
  "docstring": "",
@@ -832,7 +832,25 @@ const getFormattedDayPeriod = (dayPeriod) => {
832
832
  }
833
833
  return dayPeriod.toUpperCase();
834
834
  };
835
- const getLocalizedTime = (locale, refParts, hourCycle) => {
835
+ /**
836
+ * Including time zone options may lead to the rendered text showing a
837
+ * different time from what was selected in the Datetime, which could cause
838
+ * confusion.
839
+ */
840
+ const stripTimeZone = (formatOptions) => {
841
+ return Object.assign(Object.assign({}, formatOptions), {
842
+ /**
843
+ * Setting the time zone to UTC ensures that the value shown is always the
844
+ * same as what was selected and safeguards against older Safari bugs with
845
+ * Intl.DateTimeFormat.
846
+ */
847
+ timeZone: 'UTC',
848
+ /**
849
+ * We do not want to display the time zone name
850
+ */
851
+ timeZoneName: undefined });
852
+ };
853
+ const getLocalizedTime = (locale, refParts, hourCycle, formatOptions = { hour: 'numeric', minute: 'numeric' }) => {
836
854
  const timeParts = {
837
855
  hour: refParts.hour,
838
856
  minute: refParts.minute,
@@ -840,28 +858,12 @@ const getLocalizedTime = (locale, refParts, hourCycle) => {
840
858
  if (timeParts.hour === undefined || timeParts.minute === undefined) {
841
859
  return 'Invalid Time';
842
860
  }
843
- return new Intl.DateTimeFormat(locale, {
844
- hour: 'numeric',
845
- minute: 'numeric',
846
- /**
847
- * Setting the timeZone to UTC prevents
848
- * new Intl.DatetimeFormat from subtracting
849
- * the user's current timezone offset
850
- * when formatting the time.
851
- */
852
- timeZone: 'UTC',
861
+ return new Intl.DateTimeFormat(locale, Object.assign(Object.assign({}, stripTimeZone(formatOptions)), {
853
862
  /**
854
863
  * We use hourCycle here instead of hour12 due to:
855
864
  * https://bugs.chromium.org/p/chromium/issues/detail?id=1347316&q=hour12&can=2
856
865
  */
857
- hourCycle,
858
- /**
859
- * Setting Z at the end indicates that this
860
- * date string is in the UTC time zone. This
861
- * prevents new Date from adding the time zone
862
- * offset when getting the ISO string.
863
- */
864
- }).format(new Date(convertDataToISO(Object.assign({
866
+ hourCycle })).format(new Date(convertDataToISO(Object.assign({
865
867
  /**
866
868
  * JS uses a simplified ISO 8601 format which allows for
867
869
  * date-only formats and date-time formats, but not
@@ -947,14 +949,6 @@ const generateDayAriaLabel = (locale, today, refParts) => {
947
949
  */
948
950
  return today ? `Today, ${labelString}` : labelString;
949
951
  };
950
- /**
951
- * Gets the day of the week, month, and day
952
- * Used for the header in MD mode.
953
- */
954
- const getMonthAndDay = (locale, refParts) => {
955
- const date = getNormalizedDate(refParts);
956
- return new Intl.DateTimeFormat(locale, { weekday: 'short', month: 'short', day: 'numeric', timeZone: 'UTC' }).format(date);
957
- };
958
952
  /**
959
953
  * Given a locale and a date object,
960
954
  * return a formatted string that includes
@@ -965,15 +959,6 @@ const getMonthAndYear = (locale, refParts) => {
965
959
  const date = getNormalizedDate(refParts);
966
960
  return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric', timeZone: 'UTC' }).format(date);
967
961
  };
968
- /**
969
- * Given a locale and a date object,
970
- * return a formatted string that includes
971
- * the short month, numeric day, and full year.
972
- * Example: Apr 22, 2021
973
- */
974
- const getMonthDayAndYear = (locale, refParts) => {
975
- return getLocalizedDateTime(locale, refParts, { month: 'short', day: 'numeric', year: 'numeric' });
976
- };
977
962
  /**
978
963
  * Given a locale and a date object,
979
964
  * return a formatted string that includes
@@ -1023,7 +1008,7 @@ const getNormalizedDate = (refParts) => {
1023
1008
  */
1024
1009
  const getLocalizedDateTime = (locale, refParts, options) => {
1025
1010
  const date = getNormalizedDate(refParts);
1026
- return getDateTimeFormat(locale, options).format(date);
1011
+ return getDateTimeFormat(locale, stripTimeZone(options)).format(date);
1027
1012
  };
1028
1013
  /**
1029
1014
  * Given a locale, DatetimeParts, and options
@@ -1622,4 +1607,4 @@ const getTimeColumnsData = (locale, refParts, hourCycle, minParts, maxParts, all
1622
1607
  };
1623
1608
  };
1624
1609
 
1625
- export { getNumDaysInMonth as A, getCombinedDateColumnData as B, getMonthColumnData as C, getDayColumnData as D, getYearColumnData as E, isMonthFirstLocale as F, getTimeColumnsData as G, isLocaleDayPeriodRTL as H, getDaysOfWeek as I, getMonthAndYear as J, getDaysOfMonth as K, getHourCycle as L, getLocalizedTime as M, getMonthAndDay as N, formatValue as O, clampDate as P, parseAmPm as Q, calculateHourFromAMPM as R, getLocalizedDateTime as S, getMonthDayAndYear as T, getDay as a, isAfter as b, isSameDay as c, getPreviousMonth as d, getNextMonth as e, getPartsFromCalendarDay as f, generateDayAriaLabel as g, getNextYear as h, isBefore as i, getPreviousYear as j, getEndOfWeek as k, getStartOfWeek as l, getPreviousDay as m, getNextDay as n, getPreviousWeek as o, getNextWeek as p, parseMinParts as q, parseMaxParts as r, parseDate as s, convertToArrayOfNumbers as t, convertDataToISO as u, validateParts as v, warnIfValueOutOfBounds as w, getToday as x, getClosestValidDate as y, generateMonths as z };
1610
+ export { getNumDaysInMonth as A, getCombinedDateColumnData as B, getMonthColumnData as C, getDayColumnData as D, getYearColumnData as E, isMonthFirstLocale as F, getTimeColumnsData as G, isLocaleDayPeriodRTL as H, getDaysOfWeek as I, getMonthAndYear as J, getDaysOfMonth as K, getHourCycle as L, getLocalizedTime as M, getLocalizedDateTime as N, formatValue as O, clampDate as P, parseAmPm as Q, calculateHourFromAMPM as R, getDay as a, isAfter as b, isSameDay as c, getPreviousMonth as d, getNextMonth as e, getPartsFromCalendarDay as f, generateDayAriaLabel as g, getNextYear as h, isBefore as i, getPreviousYear as j, getEndOfWeek as k, getStartOfWeek as l, getPreviousDay as m, getNextDay as n, getPreviousWeek as o, getNextWeek as p, parseMinParts as q, parseMaxParts as r, parseDate as s, convertToArrayOfNumbers as t, convertDataToISO as u, validateParts as v, warnIfValueOutOfBounds as w, getToday as x, getClosestValidDate as y, generateMonths as z };