@aquera/nile-elements 1.3.4-beta-1.3 → 1.3.4-beta-1.5

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.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Webcomponent nile-elements following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "nile-elements",
6
- "version": "1.3.4-beta-1.3",
6
+ "version": "1.3.4-beta-1.5",
7
7
  "main": "dist/src/index.js",
8
8
  "type": "module",
9
9
  "module": "dist/src/index.js",
@@ -0,0 +1,105 @@
1
+ export function parseDateFromFormat(str: string, format: string): Date | null {
2
+ if (!str) return null;
3
+
4
+ const sepMatch = format.match(/[^A-Z]/i);
5
+ if (!sepMatch) return null;
6
+ const sep = sepMatch[0];
7
+
8
+ if (!str.includes(sep)) return null;
9
+
10
+ const parts = str.split(sep);
11
+ const fmtParts = format.split(sep);
12
+
13
+ let day: number | null = null;
14
+ let month: number | null = null;
15
+ let year: number | null = null;
16
+
17
+ for (let i = 0; i < fmtParts.length; i++) {
18
+ const f = fmtParts[i];
19
+ const v = parts[i];
20
+ if (!v) return null;
21
+
22
+ if (f === "DD") {
23
+ if (v.length !== 2) return null;
24
+ day = Number(v);
25
+ }
26
+
27
+ if (f === "MM") {
28
+ if (v.length !== 2) return null;
29
+ month = Number(v) - 1;
30
+ }
31
+
32
+ if (f === "YYYY") {
33
+ if (v.length !== 4) return null;
34
+ year = Number(v);
35
+ }
36
+ }
37
+
38
+ if (day == null || month == null || year == null) return null;
39
+
40
+ const d = new Date(year, month, day);
41
+ if (
42
+ d.getFullYear() !== year ||
43
+ d.getMonth() !== month ||
44
+ d.getDate() !== day
45
+ ) return null;
46
+
47
+ return d;
48
+ }
49
+
50
+ export function formatDateToFormat(date: Date, format: string): string {
51
+ if (!date) return "";
52
+
53
+ const day = String(date.getDate()).padStart(2, "0");
54
+ const month = String(date.getMonth() + 1).padStart(2, "0");
55
+ const year = date.getFullYear();
56
+
57
+ switch (format) {
58
+ case "DD/MM/YYYY":
59
+ return `${day}/${month}/${year}`;
60
+ case "MM/DD/YYYY":
61
+ return `${month}/${day}/${year}`;
62
+ case "YYYY/MM/DD":
63
+ return `${year}/${month}/${day}`;
64
+ case "YYYY.MM.DD":
65
+ return `${year}.${month}.${day}`;
66
+ case "DD.MM.YYYY":
67
+ return `${day}.${month}.${year}`;
68
+ default:
69
+ return `${day}/${month}/${year}`;
70
+ }
71
+ }
72
+
73
+ export function parseRangeFromFormat(
74
+ input: string,
75
+ format: string,
76
+ isRange: boolean,
77
+ separator: string
78
+ ) {
79
+ if (!isRange) {
80
+ return { first: parseDateFromFormat(input, format), second: null };
81
+ }
82
+
83
+ if (!input.includes(separator)) {
84
+ return { first: parseDateFromFormat(input, format), second: null };
85
+ }
86
+
87
+ const [firstRaw, secondRaw] = input.split(separator);
88
+
89
+ const first = parseDateFromFormat(firstRaw, format);
90
+ const second = secondRaw ? parseDateFromFormat(secondRaw, format) : null;
91
+
92
+ return { first, second };
93
+ }
94
+
95
+
96
+ export function normalizeDateRange(
97
+ first: Date | null,
98
+ second: Date | null
99
+ ): [Date | null, Date | null] {
100
+ if (first && second && first.getTime() > second.getTime()) {
101
+ return [second, first];
102
+ }
103
+ return [first, second];
104
+ }
105
+
@@ -5,10 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
-
9
-
10
8
  import {
11
- LitElement,
12
9
  html,
13
10
  CSSResultArray,
14
11
  TemplateResult,
@@ -18,156 +15,72 @@ import { styles } from './nile-date-picker.css';
18
15
  import NileElement from '../internal/nile-element';
19
16
  import { NileDropdown } from '../nile-dropdown';
20
17
 
21
- /**
22
- * Nile icon component.
23
- *
24
- * @tag nile-date-picker
25
- *
26
- */
18
+ import {
19
+ parseDateFromFormat,
20
+ formatDateToFormat,
21
+ parseRangeFromFormat,
22
+ normalizeDateRange
23
+ } from './nile-date-picker-utils';
24
+
25
+
27
26
  @customElement('nile-date-picker')
28
27
  export class NileDatePicker extends NileElement {
29
- /**
30
- * The styles for DatePicker
31
- * @remarks If you are extending this class you can extend the base styles with super. Eg `return [super(), myCustomStyles]`
32
- */
33
28
  public static get styles(): CSSResultArray {
34
29
  return [styles];
35
30
  }
36
31
 
37
32
  @property({ type: Boolean }) range = false;
38
-
39
33
  @property({ type: Boolean }) hideTypes = false;
40
-
41
34
  @property({ type: Boolean, reflect: true }) doubleClickUnselect = false;
42
-
43
35
  @property({ type: Boolean, reflect: true }) allowClear = false;
44
-
45
36
  @property({ type: Boolean }) open = false;
46
-
47
37
  @property({ type: Boolean, attribute: 'hide-time-zone' }) hideTimeZone = false;
48
-
49
- @property({ type: String, reflect: true }) type :'absolute' | 'relative' = 'absolute';
50
-
51
- @property({ type: Boolean, attribute: 'showManualInputs' })
52
- showManualInputs = false;
38
+ @property({ type: String, reflect: true }) type: 'absolute' | 'relative' = 'absolute';
39
+ @property({ type: Boolean, attribute: 'showManualInputs' }) showManualInputs = false;
53
40
 
54
41
  @property() value: any;
55
- @property({ type: Array, attribute: 'hide-duration-fields' })
56
- hideDurationFields: any = [];
57
-
42
+ @property({ type: Array, attribute: 'hide-duration-fields' }) hideDurationFields: any = [];
58
43
  @property({ attribute: 'allowedDates' }) allowedDates: any = '{}';
59
44
 
60
- // Jump to typed date activated by user
61
- @property({ type: Boolean, attribute: true, reflect: true }) jumpToTypedDate = false;
62
-
63
- // Strict input format
64
- @property({ type: String, attribute: true, reflect: true }) inputFormat = "DD/MM/YYYY";
45
+ @property({ type: Boolean, attribute: true, reflect: true }) syncDatePicker = false;
46
+ @property({ type: String, attribute: true, reflect: true }) dateFormat = "DD/MM/YYYY";
47
+ @property({ type: String, attribute: true, reflect: true }) rangeSeparator = " - ";
65
48
 
66
49
 
67
50
  @query('nile-dropdown') dropdown: NileDropdown;
68
51
 
69
- /**
70
- * Render method
71
- * @slot This is a slot test
72
- */
73
- private parseDate(str: string): Date | null {
74
- if (!str) return null;
75
-
76
- const fmt = this.inputFormat;
77
- const sepMatch = fmt.match(/[^A-Z]/i);
78
- if (!sepMatch) return null;
79
- const sep = sepMatch[0];
80
-
81
- if (!str.includes(sep)) return null;
52
+ firstUpdated() {
53
+ super.firstUpdated?.(new Map());
82
54
 
83
- const parts = str.split(sep);
84
- const fmtParts = fmt.split(sep);
55
+ if (!this.syncDatePicker) return;
85
56
 
86
- let day = null, month = null, year = null;
57
+ const input = this.querySelector("nile-input");
58
+ if (!input) return;
87
59
 
88
- for (let i = 0; i < fmtParts.length; i++) {
89
- const f = fmtParts[i];
90
- const v = parts[i];
91
- if (!v) return null;
60
+ input.addEventListener("nile-input", (e: any) => {
61
+ const text = e.detail.value;
62
+ const { first, second } = parseRangeFromFormat(text, this.dateFormat, this.range, this.rangeSeparator);
92
63
 
93
- if (f === "DD") {
94
- if (v.length !== 2) return null;
95
- day = Number(v);
64
+ if (!this.range) {
65
+ if (first) this.jumpTo(first);
66
+ return;
96
67
  }
97
68
 
98
- if (f === "MM") {
99
- if (v.length !== 2) return null;
100
- month = Number(v) - 1;
69
+ if (first && !second) {
70
+ this.jumpTo(first);
71
+ this.syncRangeCalendar(first, null);
101
72
  }
102
73
 
103
- if (f === "YYYY") {
104
- if (v.length !== 4) return null;
105
- year = Number(v);
74
+ if (first && second) {
75
+ const [start, end] = normalizeDateRange(first, second);
76
+ if (end) this.jumpTo(end);
77
+ this.syncRangeCalendar(start, end);
106
78
  }
107
- }
108
-
109
- if (day == null || month == null || year == null) return null;
110
-
111
- const d = new Date(year, month, day);
112
- if (
113
- d.getFullYear() !== year ||
114
- d.getMonth() !== month ||
115
- d.getDate() !== day
116
- ) return null;
117
-
118
- return d;
119
- }
120
-
121
-
122
- private formatDate(date: Date): string {
123
- if (!date) return "";
124
-
125
- const day = String(date.getDate()).padStart(2, "0");
126
- const month = String(date.getMonth() + 1).padStart(2, "0");
127
- const year = date.getFullYear();
128
-
129
- switch (this.inputFormat) {
130
- case "DD/MM/YYYY":
131
- return `${day}/${month}/${year}`;
132
- case "MM/DD/YYYY":
133
- return `${month}/${day}/${year}`;
134
- case "YYYY/MM/DD":
135
- return `${year}/${month}/${day}`;
136
- case "YYYY.MM.DD":
137
- return `${year}.${month}.${day}`;
138
- case "DD.MM.YYYY":
139
- return `${day}.${month}.${year}`;
140
- default:
141
- return `${day}/${month}/${year}`;
142
- }
143
- }
144
-
145
- private parseRange(input: string) {
146
- if (!this.range) {
147
- return { first: this.parseDate(input), second: null };
148
- }
149
-
150
- const RANGE_SEP = " - ";
151
-
152
- if (!input.includes(RANGE_SEP)) {
153
- return { first: this.parseDate(input), second: null };
154
- }
155
-
156
- const [firstRaw, secondRaw] = input.split(RANGE_SEP);
157
-
158
- const first = this.parseDate(firstRaw);
159
- let second = null;
160
-
161
- if (secondRaw && secondRaw.length >= 10) {
162
- second = this.parseDate(secondRaw);
163
- }
164
-
165
- return { first, second };
79
+ });
166
80
  }
167
81
 
168
82
  private jumpTo(date: Date) {
169
83
  this.open = true;
170
-
171
84
  const cal = this.shadowRoot!.querySelector("nile-calendar") as any;
172
85
  if (!cal) return;
173
86
 
@@ -177,72 +90,39 @@ export class NileDatePicker extends NileElement {
177
90
  cal.valueAttribute = date.toISOString();
178
91
  }
179
92
 
93
+
180
94
  private syncRangeCalendar(first: Date | null, second: Date | null) {
181
95
  const cal = this.shadowRoot!.querySelector("nile-calendar") as any;
182
96
  if (!cal) return;
183
97
 
184
- if (!this.range) return;
98
+ if (!this.range) return;
185
99
 
186
100
  if (first) cal.startDate = first;
187
101
  if (second) cal.endDate = second;
188
-
189
-
190
- if (first && second && first.getTime() > second.getTime()) {
191
- cal.startDate = second;
192
- cal.endDate = first;
193
- }
194
102
  }
195
- firstUpdated() {
196
- super.firstUpdated?.(new Map());
197
-
198
- if (!this.jumpToTypedDate) return;
199
-
200
- const input = this.querySelector("nile-input");
201
- if (!input) return;
202
-
203
- input.addEventListener("nile-input", (e: any) => {
204
- const text = e.detail.value;
205
- const { first, second } = this.parseRange(text);
206
103
 
207
- if (!this.range) {
208
- if (first) this.jumpTo(first);
209
- return;
210
- }
211
-
212
- if (first && !second) {
213
- this.jumpTo(first);
214
- this.syncRangeCalendar(first, null);
215
- }
216
-
217
- if (first && second) {
218
- let start = first, end = second;
219
- if (start.getTime() > end.getTime()) {
220
- [start, end] = [end, start];
221
- }
222
-
223
- this.jumpTo(end);
224
- this.syncRangeCalendar(start, end);
225
- }
226
- });
227
- }
228
-
229
-
230
104
  render(): TemplateResult {
231
105
  return html`
232
106
  <nile-dropdown .open="${this.open}" part="dd-base" .hoist="${true}" distance="6" exportparts="base">
233
107
  <slot slot="trigger" part="trigger" name="trigger"></slot>
108
+
234
109
  <nile-calendar
235
110
  .hideTypes="${this.hideTypes}"
236
- .type="${this.type}"
111
+ .type="${this.type}"
237
112
  value="${this.value}"
238
113
  .range="${this.range}"
239
- @nile-init="${(e:CustomEvent)=>e.stopPropagation()}"
240
- @nile-destroy="${(e:CustomEvent)=>e.stopPropagation()}"
241
- @nile-changed="${(e:CustomEvent)=>e.stopPropagation()}"
114
+
115
+ @nile-init="${(e: CustomEvent) => e.stopPropagation()}"
116
+ @nile-destroy="${(e: CustomEvent) => e.stopPropagation()}"
117
+ @nile-changed="${(e: CustomEvent) => e.stopPropagation()}"
118
+
242
119
  @nile-change="${this.handleChanged}"
120
+
243
121
  .allowedDates="${this.allowedDates}"
244
- @nile-type-change="${(e:CustomEvent)=>{e.stopPropagation();this.emit('nile-type-change',e.detail)}}"
245
- @nile-clear="${(e:CustomEvent)=>{e.stopPropagation();this.emit('nile-clear')}}"
122
+
123
+ @nile-type-change="${(e: CustomEvent) => { e.stopPropagation(); this.emit('nile-type-change', e.detail); }}"
124
+ @nile-clear="${(e: CustomEvent) => { e.stopPropagation(); this.emit('nile-clear'); }}"
125
+
246
126
  .hideDurationFields="${this.hideDurationFields}"
247
127
  .showManualInputs="${this.showManualInputs}"
248
128
  .doubleClickUnselect="${this.doubleClickUnselect}"
@@ -252,50 +132,45 @@ export class NileDatePicker extends NileElement {
252
132
  `;
253
133
  }
254
134
 
135
+
255
136
  handleChanged(event: CustomEvent) {
256
137
  event.stopPropagation();
257
-
258
- const detail = event.detail;
138
+
139
+ const detail = event.detail;
259
140
  const triggerInput = this.querySelector("nile-input");
260
-
261
- // SINGLE DATE
141
+
262
142
  if (!this.range) {
263
143
  const picked = detail.value;
264
-
144
+
265
145
  if (picked && triggerInput) {
266
- triggerInput.value = this.formatDate(new Date(picked));
146
+ triggerInput.value = formatDateToFormat(new Date(picked), this.dateFormat);
267
147
  triggerInput.emit("nile-input", { value: triggerInput.value });
268
148
  }
269
-
270
-
149
+
271
150
  this.emit("nile-changed", detail);
272
151
  this.emit("nile-change", detail);
273
-
152
+
274
153
  this.dropdown?.hide();
275
154
  return;
276
155
  }
277
-
278
- // RANGE MODE
156
+
279
157
  const start = detail.startDate;
280
158
  const end = detail.endDate;
281
-
159
+
282
160
  if (triggerInput) {
283
161
  let text = "";
284
- if (start) text += this.formatDate(new Date(start));
285
- if (start && end) text += " - " + this.formatDate(new Date(end));
286
-
162
+ if (start) text += formatDateToFormat(new Date(start), this.dateFormat);
163
+ if (start && end) text += " - " + formatDateToFormat(new Date(end), this.dateFormat);
164
+
287
165
  triggerInput.value = text;
288
166
  triggerInput.emit("nile-input", { value: text });
289
167
  }
290
-
291
-
168
+
292
169
  this.emit("nile-changed", detail);
293
170
  this.emit("nile-change", detail);
294
-
171
+
295
172
  this.dropdown?.hide();
296
173
  }
297
-
298
-
299
174
 
300
175
  connectedCallback() {
301
176
  super.connectedCallback();
@@ -1102,7 +1102,7 @@
1102
1102
  },
1103
1103
  {
1104
1104
  "name": "nile-date-picker",
1105
- "description": "Nile icon component.\n\nAttributes:\n\n * `range` {`boolean`} - \n\n * `hideTypes` {`boolean`} - \n\n * `doubleClickUnselect` {`boolean`} - \n\n * `allowClear` {`boolean`} - \n\n * `open` {`boolean`} - \n\n * `hide-time-zone` {`boolean`} - \n\n * `type` {`\"absolute\" | \"relative\"`} - \n\n * `showManualInputs` {`boolean`} - \n\n * `value` - \n\n * `hide-duration-fields` - \n\n * `allowedDates` - \n\n * `jumpToTypedDate` {`boolean`} - \n\n * `inputFormat` {`string`} - \n\nProperties:\n\n * `range` {`boolean`} - \n\n * `hideTypes` {`boolean`} - \n\n * `doubleClickUnselect` {`boolean`} - \n\n * `allowClear` {`boolean`} - \n\n * `open` {`boolean`} - \n\n * `hideTimeZone` {`boolean`} - \n\n * `type` {`\"absolute\" | \"relative\"`} - \n\n * `showManualInputs` {`boolean`} - \n\n * `value` - \n\n * `hideDurationFields` - \n\n * `allowedDates` - \n\n * `jumpToTypedDate` {`boolean`} - \n\n * `inputFormat` {`string`} - \n\n * `dropdown` - \n\n * `BUBBLES` {`boolean`} - \n\n * `COMPOSED` {`boolean`} - \n\n * `CANCELABLE` {`boolean`} - ",
1105
+ "description": "Attributes:\n\n * `range` {`boolean`} - \n\n * `hideTypes` {`boolean`} - \n\n * `doubleClickUnselect` {`boolean`} - \n\n * `allowClear` {`boolean`} - \n\n * `open` {`boolean`} - \n\n * `hide-time-zone` {`boolean`} - \n\n * `type` {`\"absolute\" | \"relative\"`} - \n\n * `showManualInputs` {`boolean`} - \n\n * `value` - \n\n * `hide-duration-fields` - \n\n * `allowedDates` - \n\n * `syncDatePicker` {`boolean`} - \n\n * `dateFormat` {`string`} - \n\n * `rangeSeparator` {`string`} - \n\nProperties:\n\n * `range` {`boolean`} - \n\n * `hideTypes` {`boolean`} - \n\n * `doubleClickUnselect` {`boolean`} - \n\n * `allowClear` {`boolean`} - \n\n * `open` {`boolean`} - \n\n * `hideTimeZone` {`boolean`} - \n\n * `type` {`\"absolute\" | \"relative\"`} - \n\n * `showManualInputs` {`boolean`} - \n\n * `value` - \n\n * `hideDurationFields` - \n\n * `allowedDates` - \n\n * `syncDatePicker` {`boolean`} - \n\n * `dateFormat` {`string`} - \n\n * `rangeSeparator` {`string`} - \n\n * `dropdown` - \n\n * `BUBBLES` {`boolean`} - \n\n * `COMPOSED` {`boolean`} - \n\n * `CANCELABLE` {`boolean`} - ",
1106
1106
  "attributes": [
1107
1107
  {
1108
1108
  "name": "range",
@@ -1164,13 +1164,17 @@
1164
1164
  "description": "`allowedDates` - \n\nProperty: allowedDates\n\nDefault: {}"
1165
1165
  },
1166
1166
  {
1167
- "name": "jumpToTypedDate",
1168
- "description": "`jumpToTypedDate` {`boolean`} - \n\nProperty: jumpToTypedDate\n\nDefault: false",
1167
+ "name": "syncDatePicker",
1168
+ "description": "`syncDatePicker` {`boolean`} - \n\nProperty: syncDatePicker\n\nDefault: false",
1169
1169
  "valueSet": "v"
1170
1170
  },
1171
1171
  {
1172
- "name": "inputFormat",
1173
- "description": "`inputFormat` {`string`} - \n\nProperty: inputFormat\n\nDefault: DD/MM/YYYY"
1172
+ "name": "dateFormat",
1173
+ "description": "`dateFormat` {`string`} - \n\nProperty: dateFormat\n\nDefault: DD/MM/YYYY"
1174
+ },
1175
+ {
1176
+ "name": "rangeSeparator",
1177
+ "description": "`rangeSeparator` {`string`} - \n\nProperty: rangeSeparator\n\nDefault: - "
1174
1178
  }
1175
1179
  ]
1176
1180
  },