@govtechsg/sgds-web-component 1.1.0-rc.0 → 1.1.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 (79) hide show
  1. package/base/dropdown-element.cjs.js +0 -1
  2. package/base/dropdown-element.cjs.js.map +1 -1
  3. package/base/dropdown-element.d.ts +1 -2
  4. package/base/dropdown-element.js +0 -1
  5. package/base/dropdown-element.js.map +1 -1
  6. package/components/ActionCard/index.umd.js +3 -1
  7. package/components/ActionCard/index.umd.js.map +1 -1
  8. package/components/Button/index.umd.js +3 -1
  9. package/components/Button/index.umd.js.map +1 -1
  10. package/components/Checkbox/index.umd.js +3 -1
  11. package/components/Checkbox/index.umd.js.map +1 -1
  12. package/components/ComboBox/index.umd.js +43 -26
  13. package/components/ComboBox/index.umd.js.map +1 -1
  14. package/components/Datepicker/datepicker-calendar.cjs.js +29 -14
  15. package/components/Datepicker/datepicker-calendar.cjs.js.map +1 -1
  16. package/components/Datepicker/datepicker-calendar.js +29 -14
  17. package/components/Datepicker/datepicker-calendar.js.map +1 -1
  18. package/components/Datepicker/datepicker-header.cjs.js +35 -17
  19. package/components/Datepicker/datepicker-header.cjs.js.map +1 -1
  20. package/components/Datepicker/datepicker-header.d.ts +2 -0
  21. package/components/Datepicker/datepicker-header.js +35 -18
  22. package/components/Datepicker/datepicker-header.js.map +1 -1
  23. package/components/Datepicker/datepicker-input.cjs.js +150 -0
  24. package/components/Datepicker/datepicker-input.cjs.js.map +1 -0
  25. package/components/Datepicker/datepicker-input.d.ts +24 -0
  26. package/components/Datepicker/datepicker-input.js +141 -0
  27. package/components/Datepicker/datepicker-input.js.map +1 -0
  28. package/components/Datepicker/index.js.map +1 -1
  29. package/components/Datepicker/index.umd.js +16655 -7545
  30. package/components/Datepicker/index.umd.js.map +1 -1
  31. package/components/Datepicker/sgds-datepicker.cjs.js +207 -150
  32. package/components/Datepicker/sgds-datepicker.cjs.js.map +1 -1
  33. package/components/Datepicker/sgds-datepicker.cjs2.js +1 -1
  34. package/components/Datepicker/sgds-datepicker.d.ts +38 -13
  35. package/components/Datepicker/sgds-datepicker.js +209 -152
  36. package/components/Datepicker/sgds-datepicker.js.map +1 -1
  37. package/components/Datepicker/sgds-datepicker2.js +1 -1
  38. package/components/Dropdown/index.umd.js +8 -3
  39. package/components/Dropdown/index.umd.js.map +1 -1
  40. package/components/Dropdown/sgds-dropdown.cjs.js +5 -1
  41. package/components/Dropdown/sgds-dropdown.cjs.js.map +1 -1
  42. package/components/Dropdown/sgds-dropdown.d.ts +4 -3
  43. package/components/Dropdown/sgds-dropdown.js +5 -1
  44. package/components/Dropdown/sgds-dropdown.js.map +1 -1
  45. package/components/FileUpload/index.umd.js +3 -1
  46. package/components/FileUpload/index.umd.js.map +1 -1
  47. package/components/Input/index.umd.js +43 -25
  48. package/components/Input/index.umd.js.map +1 -1
  49. package/components/Input/sgds-input.cjs.js +40 -24
  50. package/components/Input/sgds-input.cjs.js.map +1 -1
  51. package/components/Input/sgds-input.d.ts +15 -9
  52. package/components/Input/sgds-input.js +40 -24
  53. package/components/Input/sgds-input.js.map +1 -1
  54. package/components/Mainnav/index.umd.js +0 -1
  55. package/components/Mainnav/index.umd.js.map +1 -1
  56. package/components/QuantityToggle/index.umd.js +3 -1
  57. package/components/QuantityToggle/index.umd.js.map +1 -1
  58. package/components/Radio/index.umd.js +3 -1
  59. package/components/Radio/index.umd.js.map +1 -1
  60. package/components/Textarea/index.umd.js +3 -1
  61. package/components/Textarea/index.umd.js.map +1 -1
  62. package/components/index.umd.js +9905 -791
  63. package/components/index.umd.js.map +1 -1
  64. package/index.umd.js +9905 -791
  65. package/index.umd.js.map +1 -1
  66. package/package.json +2 -2
  67. package/react/datepicker/index.cjs.js +1 -2
  68. package/react/datepicker/index.cjs.js.map +1 -1
  69. package/react/datepicker/index.js +1 -2
  70. package/react/datepicker/index.js.map +1 -1
  71. package/utils/form.cjs.js +3 -1
  72. package/utils/form.cjs.js.map +1 -1
  73. package/utils/form.js +3 -1
  74. package/utils/form.js.map +1 -1
  75. package/utils/time.cjs.js +18 -4
  76. package/utils/time.cjs.js.map +1 -1
  77. package/utils/time.d.ts +17 -0
  78. package/utils/time.js +18 -4
  79. package/utils/time.js.map +1 -1
@@ -1,19 +1,21 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { ScopedElementsMixin } from '@open-wc/scoped-elements';
3
+ import { parse, format } from 'date-fns';
3
4
  import { html } from 'lit';
4
- import { property, state, queryAsync } from 'lit/decorators.js';
5
+ import { property, state, queryAsync, query } from 'lit/decorators.js';
5
6
  import { live } from 'lit/directives/live.js';
6
7
  import { ref } from 'lit/directives/ref.js';
7
8
  import { DropdownElement } from '../../base/dropdown-element.js';
8
9
  import { watch } from '../../utils/watch.js';
9
- import { SgdsInput } from '../Input/sgds-input.js';
10
10
  import { DatepickerCalendar } from './datepicker-calendar.js';
11
11
  import { DatepickerHeader } from './datepicker-header.js';
12
+ import { DatepickerInput } from './datepicker-input.js';
12
13
  import css_248z from './sgds-datepicker2.js';
13
- import { sortAscDates } from '../../utils/time.js';
14
+ import { setTimeToNoon, DATE_PATTERNS } from '../../utils/time.js';
15
+ import { classMap } from 'lit/directives/class-map.js';
14
16
 
15
17
  /**
16
- * @summary The `DatePicker` Component is built using `Dropdown`, `Input` and `Button` components. By default, the Calendar points to current date and input has no value. The input is a read-only and users can only pick dates using the Calendar.
18
+ * @summary The `DatePicker` Component is built using `Dropdown`, `Input` and `Button` components. By default, the Calendar points to today's date and input has no value. Users can either pick dates from the calendar or type dates through the input
17
19
  *
18
20
  * @event sgds-change-date - Emitted when the state of datepicker's input changes during first load, close button reset click & date click. Date values can be accessed via event.target.value
19
21
  *
@@ -34,56 +36,70 @@ class SgdsDatepicker extends ScopedElementsMixin(DropdownElement) {
34
36
  /**@internal */
35
37
  static get scopedElements() {
36
38
  return {
37
- "sgds-input": SgdsInput,
39
+ "sgds-datepicker-input": DatepickerInput,
38
40
  "sgds-datepicker-calendar": DatepickerCalendar,
39
41
  "sgds-datepicker-header": DatepickerHeader
40
42
  };
41
43
  }
44
+ /** Checks for validity and shows the browser's validation message if the control is invalid. */
45
+ reportValidity() {
46
+ return this._internals.reportValidity();
47
+ }
42
48
  constructor() {
43
49
  super();
44
50
  /** When true, adds required attribute to input element */
45
51
  this.required = false;
46
52
  /** When true, adds disabled attribute to input and button element */
47
53
  this.disabled = false;
54
+ /** The initial value of DatePicker on first load for single & range mode as array of string. eg.'["22/12/2023"]' for single & '["22/12/2023","25/12/2023"]' for range respectively */
55
+ this.initialValue = [];
48
56
  /** Date format reflected on input */
49
57
  this.dateFormat = "DD/MM/YYYY";
58
+ /** ISO date string to set the lowest allowable date value. e.g. "2016-05-19T12:00:00.000Z" */
59
+ this.minDate = "";
60
+ /** ISO date string to set the highest allowable date value. e.g. "2016-05-19T12:00:00.000Z" */
61
+ this.maxDate = "";
50
62
  /** Changes DatePicker to single date selection or range date selection */
51
63
  this.mode = "single";
52
- /** @internal */
64
+ /**Feedback text for error state when date input is invalid */
65
+ this.invalidFeedback = "Please enter a valid date";
66
+ /** The datepicker input's label */
67
+ this.label = "";
68
+ /** The datepicker input's hint text below the label */
69
+ this.hintText = "";
70
+ /** Controls auto-flipping of menu */
71
+ this.noFlip = false;
72
+ /** The drop position of menu relative to the toggle button */
73
+ this.drop = "down";
74
+ this.value = "";
53
75
  this.view = "days";
54
- /** @internal */
55
76
  this.selectedDateRange = [];
56
- /** @internal */
57
- this.displayDate = new Date();
58
- /** @internal */
59
- this.focusedDate = new Date();
60
77
  this.focusedTabIndex = 3;
61
78
  this._makeInputValueString = (startDate, endDate, dateFormat) => {
62
79
  if (!startDate && !endDate)
63
- return "";
64
- const formatDate = (date) => {
65
- if (!(date instanceof Date) || isNaN(date.getTime())) {
66
- return ""; // Return an empty string if the date is not a valid Date object
80
+ return this.value;
81
+ const formatDate = (date) => format(date, DATE_PATTERNS[dateFormat].fnsPattern);
82
+ switch (this.mode) {
83
+ case "single": {
84
+ if (startDate) {
85
+ this.value = formatDate(startDate);
86
+ }
87
+ break;
88
+ }
89
+ case "range": {
90
+ if (startDate && endDate) {
91
+ this.value = `${formatDate(startDate)} - ${formatDate(endDate)}`;
92
+ }
93
+ if (startDate && !endDate) {
94
+ this.value = `${formatDate(startDate)} - ${this.dateFormat.toLowerCase()}`;
95
+ }
96
+ break;
67
97
  }
68
- const month = date.getMonth() + 1;
69
- const day = date.getDate();
70
- const separator = "/";
71
- const formattedMonth = month > 9 ? month.toString() : `0${month}`;
72
- const formattedDay = day > 9 ? day.toString() : `0${day}`;
73
- return dateFormat === "YYYY/MM/DD"
74
- ? `${date.getFullYear()}${separator}${formattedMonth}${separator}${formattedDay}`
75
- : dateFormat === "DD/MM/YYYY"
76
- ? `${formattedDay}${separator}${formattedMonth}${separator}${date.getFullYear()}`
77
- : `${formattedMonth}${separator}${formattedDay}${separator}${date.getFullYear()}`;
78
- };
79
- if (startDate && endDate) {
80
- return `${formatDate(startDate)} - ${formatDate(endDate)}`;
81
- }
82
- if (startDate) {
83
- return formatDate(startDate);
84
98
  }
85
- return "";
99
+ return this.value;
86
100
  };
101
+ this._internals = this.attachInternals();
102
+ /**@internal */
87
103
  this.modifierOpt = [
88
104
  {
89
105
  name: "offset",
@@ -93,83 +109,47 @@ class SgdsDatepicker extends ScopedElementsMixin(DropdownElement) {
93
109
  }
94
110
  ];
95
111
  }
96
- connectedCallback() {
112
+ async connectedCallback() {
97
113
  super.connectedCallback();
98
114
  this.addEventListener("sgds-view", this._handleViewChanged);
99
115
  this.addEventListener("sgds-change-calendar", this._handleDateChanged);
100
116
  this.addEventListener("sgds-update-focus", this._handleFocusDateChanged);
101
117
  this.addEventListener("sgds-selectmonth", this._handleSelectMonth);
102
118
  this.addEventListener("sgds-selectyear", this._handleSelectYear);
103
- this.addEventListener("sgds-selectdates", this._handleSelectDates);
119
+ this.addEventListener("sgds-selectdates", this._handleSelectDatesAndClose);
120
+ this.addEventListener("sgds-selectdates-input", this._handleSelectDatesInput);
121
+ this.addEventListener("sgds-empty-input", this._handleEmptyInput);
104
122
  this.addEventListener("keydown", this._handleTab);
105
123
  this.addEventListener("sgds-hide", this._handleCloseMenu);
124
+ this.initialDisplayDate = this.displayDate || new Date();
106
125
  if (this.initialValue && this.initialValue.length > 0) {
107
126
  // Validate initialValue against the dateFormat regex
108
127
  const dateFormatRegex = new RegExp(this._getDateFormatRegex());
109
- const startDateString = this.initialValue[0];
110
- if (!dateFormatRegex.test(startDateString)) {
111
- // Handle invalid date format in initialValue
112
- console.error("Invalid date format in initialValue:", startDateString);
113
- return;
128
+ // const startDateString = this.initialValue[0];
129
+ const invalidDates = this.initialValue.filter(v => !dateFormatRegex.test(v));
130
+ if (invalidDates.length > 0) {
131
+ return console.error("Invalid date format in initialValue:", invalidDates);
114
132
  }
115
- const startDate = this._parseDateStringToDate(startDateString);
116
- if (this.mode === "single" && startDate) {
117
- // Single mode
118
- this.selectedDateRange = [startDate];
119
- this.displayDate = startDate;
120
- }
121
- else if (this.mode === "range" && this.initialValue.length === 2) {
122
- // Range mode
123
- const endDateString = this.initialValue[1];
124
- if (!dateFormatRegex.test(endDateString)) {
125
- // Handle invalid date format in initialValue
126
- console.error("Invalid date format in initialValue:", endDateString);
127
- return;
128
- }
129
- const endDate = this._parseDateStringToDate(endDateString);
130
- if (startDate && endDate) {
131
- this.selectedDateRange = [startDate, endDate];
132
- this.selectedDateRange = sortAscDates(this.selectedDateRange);
133
- // this.selectedDateRange.sort((a, b) => a.getTime() - b.getTime());
134
- this.displayDate = startDate;
135
- }
133
+ else {
134
+ const initialSelectedDates = this.initialValue.map(v => setTimeToNoon(parse(v, DATE_PATTERNS[this.dateFormat].fnsPattern, new Date())));
135
+ this._handleSelectDates(initialSelectedDates);
136
136
  }
137
137
  }
138
- if (this.selectedDateRange && this.selectedDateRange.length > 0) {
139
- // Get the formattedDate value for the selected dates
140
- const formattedDate = this._makeInputValueString(this.selectedDateRange[0], this.selectedDateRange[1], this.dateFormat);
141
- this.value = formattedDate;
142
- }
143
138
  else {
144
- // If selectedDateRange is empty, emit sgds-change-date event with an empty string
145
- this.value = "";
139
+ this.displayDate = this.initialDisplayDate;
146
140
  }
147
141
  }
148
142
  async firstUpdated() {
149
143
  super.firstUpdated();
150
144
  if (this.menuIsOpen) {
151
- const input = await this.dropdownRef;
145
+ const input = await this.datepickerInputAsync;
152
146
  this.showMenu();
153
147
  const cal = await this.calendar;
154
148
  cal.focusOnCalendar(input);
155
149
  }
156
- }
157
- _parseDateStringToDate(dateString) {
158
- let year, month, day;
159
- switch (this.dateFormat) {
160
- case "MM/DD/YYYY":
161
- [month, day, year] = dateString.split("/");
162
- break;
163
- case "DD/MM/YYYY":
164
- [day, month, year] = dateString.split("/");
165
- break;
166
- case "YYYY/MM/DD":
167
- [year, month, day] = dateString.split("/");
168
- break;
169
- default:
170
- return null;
171
- }
172
- return new Date(`${year}-${month}-${day}`);
150
+ const shadowInput = await this.datepickerInput.shadowInput;
151
+ this._manageInternalsDefault(shadowInput);
152
+ this._internals.setValidity(shadowInput.validity, shadowInput.validationMessage, shadowInput);
173
153
  }
174
154
  /** @internal */
175
155
  _getDateFormatRegex() {
@@ -187,6 +167,9 @@ class SgdsDatepicker extends ScopedElementsMixin(DropdownElement) {
187
167
  .replace("/", "\\/"));
188
168
  }
189
169
  _handleTab(event) {
170
+ if (!this.menuIsOpen) {
171
+ return;
172
+ }
190
173
  const tabIndexArray = Array(4);
191
174
  if (event.shiftKey && event.key === "Tab") {
192
175
  event.preventDefault();
@@ -199,10 +182,11 @@ class SgdsDatepicker extends ScopedElementsMixin(DropdownElement) {
199
182
  }
200
183
  _handleValueChange() {
201
184
  this.emit("sgds-change-date");
185
+ this._setInternalFormValue(this.value);
202
186
  }
203
187
  async _handleCloseMenu() {
204
188
  if (this.selectedDateRange.length === 0) {
205
- this.displayDate = new Date();
189
+ this.displayDate = this.initialDisplayDate;
206
190
  }
207
191
  else {
208
192
  const selectedDatesLength = this.selectedDateRange.length;
@@ -211,28 +195,34 @@ class SgdsDatepicker extends ScopedElementsMixin(DropdownElement) {
211
195
  calendar._updateFocusedDate();
212
196
  }
213
197
  }
214
- _handleSelectDates(event) {
215
- const newSelectedDates = event.detail;
198
+ _handleSelectDatesInput(event) {
199
+ this._handleSelectDates(event.detail);
200
+ this._manageInternalsDefault(this._shadowInput);
201
+ }
202
+ async _handleSelectDates(newSelectedDates) {
203
+ newSelectedDates.sort((a, b) => a.getTime() - b.getTime());
216
204
  this.displayDate = newSelectedDates[0];
217
205
  this.focusedDate = newSelectedDates[0];
218
- if (this.mode === "range") {
219
- // Sort the newSelectedDates array in ascending order
220
- newSelectedDates.sort((a, b) => a.getTime() - b.getTime());
221
- this.selectedDateRange = newSelectedDates;
222
- if (this.selectedDateRange.length === 2) {
223
- this.hideMenu();
224
- }
225
- }
226
- else if (this.mode === "single") {
227
- this.selectedDateRange = [newSelectedDates[0]];
228
- if (this.selectedDateRange.length === 1) {
229
- this.hideMenu();
230
- }
231
- }
206
+ this.selectedDateRange = newSelectedDates;
232
207
  // Get the formattedDate value for the selected dates
233
208
  const formattedDate = this._makeInputValueString(this.selectedDateRange[0], this.selectedDateRange[1], this.dateFormat);
234
209
  // Set formattedDate value as the new value for sgds-input
235
210
  this.value = formattedDate;
211
+ const input = await this.datepickerInputAsync;
212
+ input.updateMaskValue();
213
+ }
214
+ get _shadowInput() {
215
+ return this.datepickerInput.shadowRoot.querySelector("input");
216
+ }
217
+ _handleSelectDatesAndClose(event) {
218
+ this._handleSelectDates(event.detail);
219
+ if (this.mode === "range" && this.selectedDateRange.length === 2) {
220
+ this.hideMenu();
221
+ }
222
+ else if (this.mode === "single" && this.selectedDateRange.length === 1) {
223
+ this.hideMenu();
224
+ }
225
+ this._manageInternalsValid();
236
226
  }
237
227
  /** update latest view state from datepicker-header */
238
228
  _handleViewChanged(event) {
@@ -250,31 +240,51 @@ class SgdsDatepicker extends ScopedElementsMixin(DropdownElement) {
250
240
  _handleSelectYear(event) {
251
241
  this.displayDate = event.detail;
252
242
  }
253
- _handleButtonResetClick() {
254
- this.displayDate = new Date();
243
+ async _handleInvalidInput() {
244
+ this.selectedDateRange = [];
245
+ this.displayDate = this.initialDisplayDate;
246
+ this._manageInternalsBadInput();
247
+ }
248
+ async _handleButtonResetClick() {
249
+ this.displayDate = this.initialDisplayDate;
255
250
  this.selectedDateRange = [];
256
251
  this.value = "";
257
252
  this.view = "days";
258
253
  this.hideMenu();
254
+ const input = await this.datepickerInputAsync;
255
+ input.setInvalid(false);
256
+ input.destroyInputMask();
257
+ await input.applyInputMask();
258
+ this._manageInternalsRequired();
259
+ }
260
+ async _handleEmptyInput() {
261
+ this._manageInternalsRequired();
262
+ }
263
+ _manageInternalsRequired() {
264
+ this.required
265
+ ? this._internals.setValidity({
266
+ valueMissing: true
267
+ }, "Please fill in this field", this._shadowInput)
268
+ : this._internals.setValidity({});
269
+ }
270
+ _manageInternalsBadInput() {
271
+ this._internals.setValidity({
272
+ badInput: true
273
+ }, "The chosen date(s) are invalid", this._shadowInput);
274
+ }
275
+ _manageInternalsValid() {
276
+ this._internals.setValidity({});
277
+ }
278
+ _manageInternalsDefault(inputEl) {
279
+ this._internals.setValidity(inputEl.validity, inputEl.validationMessage, inputEl);
280
+ }
281
+ _setInternalFormValue(value) {
282
+ this._internals.setFormValue(value);
283
+ }
284
+ async _handleInputMaskChange(e) {
285
+ this.value = e.detail;
259
286
  }
260
287
  render() {
261
- let formattedDate = "";
262
- if (this.mode === "single") {
263
- formattedDate = this._makeInputValueString(this.selectedDateRange[0], undefined, this.dateFormat);
264
- }
265
- else if (this.mode === "range") {
266
- formattedDate = this._makeInputValueString(this.selectedDateRange[0], this.selectedDateRange[1], this.dateFormat);
267
- }
268
- const getPlaceholder = () => {
269
- const validDateFormats = ["MM/DD/YYYY", "DD/MM/YYYY", "YYYY/MM/DD"];
270
- if (this.mode === "range" && validDateFormats.includes(this.dateFormat)) {
271
- return `${this.dateFormat.toLowerCase()} - ${this.dateFormat.toLowerCase()}`;
272
- }
273
- else if (this.mode === "single" && validDateFormats.includes(this.dateFormat)) {
274
- return this.dateFormat.toLowerCase();
275
- }
276
- return "";
277
- };
278
288
  const svgEl = html `
279
289
  <svg
280
290
  xmlns="http://www.w3.org/2000/svg"
@@ -288,37 +298,62 @@ class SgdsDatepicker extends ScopedElementsMixin(DropdownElement) {
288
298
  d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
289
299
  />
290
300
  </svg>
291
- `;
292
- const svgIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-calendar" viewBox="0 0 16 16">
293
- <path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
294
- </svg>
295
301
  `;
296
302
  return html `
297
303
  <div>
298
- <sgds-input
299
- id="myInput"
300
- icon=${svgIcon}
301
- .value=${live(formattedDate)}
302
- inputClasses="rounded-0 rounded-start"
303
- placeholder="${getPlaceholder()}"
304
- aria-expanded="${this.menuIsOpen}"
305
- ${ref(this.myDropdown)}
306
- @click=${() => this.toggleMenu()}
307
- readonly
304
+ <sgds-datepicker-input
305
+ .value=${live(this.value)}
308
306
  ?required=${this.required}
309
307
  ?disabled=${this.disabled}
310
- role="combobox"
311
- aria-haspopup="dialog"
312
- aria-controls=${this.dropdownMenuId}
313
- ></sgds-input>
314
- <button
315
- ?disabled=${this.disabled}
316
- class="btn sgds rounded-0 d-flex align-items-center"
317
- aria-label="reset the datepicker"
318
- @click=${() => this._handleButtonResetClick()}
308
+ placeholder=""
309
+ ${ref(this.myDropdown)}
310
+ mode=${this.mode}
311
+ dateFormat=${this.dateFormat}
312
+ invalidFeedback=${this.invalidFeedback}
313
+ @sgds-mask-input-change=${this._handleInputMaskChange}
314
+ @sgds-invalid-input=${this._handleInvalidInput}
315
+ minDate=${this.minDate}
316
+ maxDate=${this.maxDate}
317
+ label=${this.label}
318
+ hintText=${this.hintText}
319
+ name=${this.name}
319
320
  >
320
- ${svgEl}
321
- </button>
321
+ <button
322
+ slot="calendar-btn"
323
+ class=${classMap({
324
+ "sgds btn rounded-0 border btn-outline-dark": true
325
+ })}
326
+ aria-expanded="${this.menuIsOpen}"
327
+ aria-haspopup="dialog"
328
+ aria-controls=${this.dropdownMenuId}
329
+ @click=${() => this.toggleMenu()}
330
+ aria-label=${this.menuIsOpen ? "Close Calendar" : "Open Calendar"}
331
+ ?disabled=${this.disabled}
332
+ >
333
+ <svg
334
+ xmlns="http://www.w3.org/2000/svg"
335
+ width="16"
336
+ height="16"
337
+ fill="currentColor"
338
+ class="bi bi-calendar"
339
+ viewBox="0 0 16 16"
340
+ >
341
+ <path
342
+ d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5M1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4z"
343
+ />
344
+ </svg>
345
+ </button>
346
+ <button
347
+ slot="reset-btn"
348
+ ?disabled=${this.disabled}
349
+ class="btn sgds rounded-0 reset-btn"
350
+ @click=${() => this._handleButtonResetClick()}
351
+ aria-label="Reset Datepicker"
352
+ >
353
+ ${svgEl}
354
+ </button>
355
+ </sgds-datepicker-input>
356
+
322
357
  <ul
323
358
  id=${this.dropdownMenuId}
324
359
  class="sgds datepicker dropdown-menu"
@@ -349,9 +384,13 @@ class SgdsDatepicker extends ScopedElementsMixin(DropdownElement) {
349
384
  }
350
385
  }
351
386
  SgdsDatepicker.styles = [DropdownElement.styles, css_248z];
387
+ SgdsDatepicker.formAssociated = true;
352
388
  __decorate([
353
389
  property({ type: Boolean, reflect: true })
354
390
  ], SgdsDatepicker.prototype, "required", void 0);
391
+ __decorate([
392
+ property({ reflect: true })
393
+ ], SgdsDatepicker.prototype, "name", void 0);
355
394
  __decorate([
356
395
  property({ type: Boolean, reflect: true })
357
396
  ], SgdsDatepicker.prototype, "disabled", void 0);
@@ -370,6 +409,24 @@ __decorate([
370
409
  __decorate([
371
410
  property({ type: String, reflect: true })
372
411
  ], SgdsDatepicker.prototype, "mode", void 0);
412
+ __decorate([
413
+ property({ type: String, reflect: true })
414
+ ], SgdsDatepicker.prototype, "invalidFeedback", void 0);
415
+ __decorate([
416
+ property({ reflect: true })
417
+ ], SgdsDatepicker.prototype, "label", void 0);
418
+ __decorate([
419
+ property({ reflect: true })
420
+ ], SgdsDatepicker.prototype, "hintText", void 0);
421
+ __decorate([
422
+ property({ type: Boolean, reflect: true, state: false })
423
+ ], SgdsDatepicker.prototype, "noFlip", void 0);
424
+ __decorate([
425
+ property({ type: String, reflect: true, state: false })
426
+ ], SgdsDatepicker.prototype, "drop", void 0);
427
+ __decorate([
428
+ property({ attribute: false })
429
+ ], SgdsDatepicker.prototype, "displayDate", void 0);
373
430
  __decorate([
374
431
  state()
375
432
  ], SgdsDatepicker.prototype, "value", void 0);
@@ -379,21 +436,21 @@ __decorate([
379
436
  __decorate([
380
437
  state()
381
438
  ], SgdsDatepicker.prototype, "selectedDateRange", void 0);
382
- __decorate([
383
- state()
384
- ], SgdsDatepicker.prototype, "displayDate", void 0);
385
439
  __decorate([
386
440
  state()
387
441
  ], SgdsDatepicker.prototype, "focusedDate", void 0);
388
442
  __decorate([
389
443
  state()
390
444
  ], SgdsDatepicker.prototype, "focusedTabIndex", void 0);
391
- __decorate([
392
- queryAsync("sgds-input")
393
- ], SgdsDatepicker.prototype, "dropdownRef", void 0);
394
445
  __decorate([
395
446
  queryAsync("sgds-datepicker-calendar")
396
447
  ], SgdsDatepicker.prototype, "calendar", void 0);
448
+ __decorate([
449
+ queryAsync("sgds-datepicker-input")
450
+ ], SgdsDatepicker.prototype, "datepickerInputAsync", void 0);
451
+ __decorate([
452
+ query("sgds-datepicker-input")
453
+ ], SgdsDatepicker.prototype, "datepickerInput", void 0);
397
454
  __decorate([
398
455
  watch("value")
399
456
  ], SgdsDatepicker.prototype, "_handleValueChange", null);