@nyaruka/temba-components 0.127.0 → 0.129.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 (109) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/demo/chart/horizontal-demo.html +81 -0
  3. package/demo/components/datepicker/example.html +63 -0
  4. package/demo/components/datepicker/range-picker-demo.html +161 -0
  5. package/demo/data/flows/sample-flow.json +127 -100
  6. package/demo/index.html +8 -0
  7. package/demo/static/css/prism.css +2 -0
  8. package/demo/static/js/prism-loader.js +12 -0
  9. package/demo/sticky-note-demo.html +152 -0
  10. package/demo/styles.css +71 -1
  11. package/dist/locales/es.js +5 -5
  12. package/dist/locales/es.js.map +1 -1
  13. package/dist/locales/fr.js +5 -5
  14. package/dist/locales/fr.js.map +1 -1
  15. package/dist/locales/locale-codes.js +11 -2
  16. package/dist/locales/locale-codes.js.map +1 -1
  17. package/dist/locales/pt.js +5 -5
  18. package/dist/locales/pt.js.map +1 -1
  19. package/dist/temba-components.js +509 -87
  20. package/dist/temba-components.js.map +1 -1
  21. package/out-tsc/src/chart/TembaChart.js +136 -62
  22. package/out-tsc/src/chart/TembaChart.js.map +1 -1
  23. package/out-tsc/src/datepicker/DatePicker.js +11 -1
  24. package/out-tsc/src/datepicker/DatePicker.js.map +1 -1
  25. package/out-tsc/src/datepicker/RangePicker.js +595 -0
  26. package/out-tsc/src/datepicker/RangePicker.js.map +1 -0
  27. package/out-tsc/src/flow/Editor.js +210 -1
  28. package/out-tsc/src/flow/Editor.js.map +1 -1
  29. package/out-tsc/src/flow/EditorNode.js +98 -139
  30. package/out-tsc/src/flow/EditorNode.js.map +1 -1
  31. package/out-tsc/src/flow/StickyNote.js +272 -0
  32. package/out-tsc/src/flow/StickyNote.js.map +1 -0
  33. package/out-tsc/src/interfaces.js +1 -0
  34. package/out-tsc/src/interfaces.js.map +1 -1
  35. package/out-tsc/src/list/RunList.js +2 -1
  36. package/out-tsc/src/list/RunList.js.map +1 -1
  37. package/out-tsc/src/list/SortableList.js +9 -0
  38. package/out-tsc/src/list/SortableList.js.map +1 -1
  39. package/out-tsc/src/locales/es.js +5 -5
  40. package/out-tsc/src/locales/es.js.map +1 -1
  41. package/out-tsc/src/locales/fr.js +5 -5
  42. package/out-tsc/src/locales/fr.js.map +1 -1
  43. package/out-tsc/src/locales/locale-codes.js +11 -2
  44. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  45. package/out-tsc/src/locales/pt.js +5 -5
  46. package/out-tsc/src/locales/pt.js.map +1 -1
  47. package/out-tsc/src/store/AppState.js +33 -0
  48. package/out-tsc/src/store/AppState.js.map +1 -1
  49. package/out-tsc/src/vectoricon/index.js +2 -1
  50. package/out-tsc/src/vectoricon/index.js.map +1 -1
  51. package/out-tsc/temba-modules.js +5 -1
  52. package/out-tsc/temba-modules.js.map +1 -1
  53. package/out-tsc/test/temba-chart.test.js +36 -0
  54. package/out-tsc/test/temba-chart.test.js.map +1 -1
  55. package/out-tsc/test/temba-datepicker.test.js +1 -1
  56. package/out-tsc/test/temba-datepicker.test.js.map +1 -1
  57. package/out-tsc/test/temba-flow-editor-node.test.js +249 -5
  58. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  59. package/out-tsc/test/temba-range-picker.test.js +123 -0
  60. package/out-tsc/test/temba-range-picker.test.js.map +1 -0
  61. package/out-tsc/test/temba-select.test.js +10 -16
  62. package/out-tsc/test/temba-select.test.js.map +1 -1
  63. package/out-tsc/test/temba-webchat.test.js +4 -0
  64. package/out-tsc/test/temba-webchat.test.js.map +1 -1
  65. package/out-tsc/test/utils.test.js +62 -0
  66. package/out-tsc/test/utils.test.js.map +1 -1
  67. package/package.json +1 -1
  68. package/screenshots/truth/datepicker/range-picker-all.png +0 -0
  69. package/screenshots/truth/datepicker/range-picker-button-states.png +0 -0
  70. package/screenshots/truth/datepicker/range-picker-default.png +0 -0
  71. package/screenshots/truth/datepicker/range-picker-editing-start.png +0 -0
  72. package/screenshots/truth/datepicker/range-picker-initial-values.png +0 -0
  73. package/screenshots/truth/datepicker/range-picker-min-max.png +0 -0
  74. package/screenshots/truth/datepicker/range-picker-week.png +0 -0
  75. package/screenshots/truth/datepicker/range-picker-year.png +0 -0
  76. package/screenshots/truth/sticky-note/blue.png +0 -0
  77. package/screenshots/truth/sticky-note/gray.png +0 -0
  78. package/screenshots/truth/sticky-note/green.png +0 -0
  79. package/screenshots/truth/sticky-note/pink.png +0 -0
  80. package/screenshots/truth/sticky-note/yellow.png +0 -0
  81. package/screenshots/truth/webchat/connected-state.png +0 -0
  82. package/src/chart/TembaChart.ts +144 -66
  83. package/src/datepicker/DatePicker.ts +9 -1
  84. package/src/datepicker/RangePicker.ts +602 -0
  85. package/src/flow/Editor.ts +252 -2
  86. package/src/flow/EditorNode.ts +98 -156
  87. package/src/flow/StickyNote.ts +284 -0
  88. package/src/interfaces.ts +2 -1
  89. package/src/list/RunList.ts +2 -1
  90. package/src/list/SortableList.ts +11 -0
  91. package/src/locales/es.ts +18 -13
  92. package/src/locales/fr.ts +18 -13
  93. package/src/locales/locale-codes.ts +11 -2
  94. package/src/locales/pt.ts +18 -13
  95. package/src/store/AppState.ts +51 -1
  96. package/src/store/flow-definition.d.ts +8 -0
  97. package/src/vectoricon/index.ts +2 -1
  98. package/static/svg/index.pdf +137 -0
  99. package/temba-modules.ts +5 -1
  100. package/test/temba-chart.test.ts +47 -0
  101. package/test/temba-datepicker.test.ts +1 -1
  102. package/test/temba-flow-editor-node.test.ts +322 -6
  103. package/test/temba-range-picker.test.ts +193 -0
  104. package/test/temba-select.test.ts +11 -19
  105. package/test/temba-webchat.test.ts +7 -0
  106. package/test/utils.test.ts +98 -0
  107. package/web-dev-server.config.mjs +30 -22
  108. package/web-test-runner.config.mjs +2 -0
  109. package/demo/datepicker/example.html +0 -69
@@ -0,0 +1,595 @@
1
+ import { __decorate } from "tslib";
2
+ import { property } from 'lit/decorators.js';
3
+ import { RapidElement } from '../RapidElement';
4
+ import { DateTime } from 'luxon';
5
+ import { html, css } from 'lit';
6
+ import { CustomEventType } from '../interfaces';
7
+ export class RangePicker extends RapidElement {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.startDate = '';
11
+ this.endDate = '';
12
+ this.editingStart = false;
13
+ this.editingEnd = false;
14
+ this.selectedRange = '';
15
+ this.minDate = '2012-01-01';
16
+ this.maxDate = DateTime.now().toISODate();
17
+ }
18
+ handleStartClick() {
19
+ this.editingStart = true;
20
+ }
21
+ handleEndClick() {
22
+ this.editingEnd = true;
23
+ }
24
+ setRange(type) {
25
+ const today = DateTime.now().toISODate();
26
+ let start = '';
27
+ if (type === 'W') {
28
+ start = DateTime.now().minus({ days: 6 }).toISODate();
29
+ }
30
+ else if (type === 'M') {
31
+ start = DateTime.now().minus({ months: 1 }).plus({ days: 1 }).toISODate();
32
+ }
33
+ else if (type === 'Y') {
34
+ start = DateTime.now().minus({ years: 1 }).plus({ days: 1 }).toISODate();
35
+ }
36
+ else if (type === 'ALL') {
37
+ start = this.minDate || '2012-01-01';
38
+ }
39
+ this.startDate = start;
40
+ this.endDate = today;
41
+ this.selectedRange = type;
42
+ this.editingStart = false;
43
+ this.editingEnd = false;
44
+ this.fireCustomEvent(CustomEventType.DateRangeChanged, {
45
+ start: this.startDate,
46
+ end: this.endDate,
47
+ range: this.selectedRange
48
+ });
49
+ }
50
+ setValidRange(type, value) {
51
+ // Enforce min/max
52
+ let newValue = value;
53
+ if (newValue < this.minDate)
54
+ newValue = this.minDate;
55
+ if (newValue > this.maxDate)
56
+ newValue = this.maxDate;
57
+ const start = DateTime.fromISO(type === 'start' ? newValue : this.startDate);
58
+ const end = DateTime.fromISO(type === 'end' ? newValue : this.endDate);
59
+ if (!start.isValid || !end.isValid)
60
+ return;
61
+ if (start > end) {
62
+ if (type === 'start') {
63
+ this.startDate = newValue;
64
+ this.endDate = start.toISODate();
65
+ }
66
+ else {
67
+ this.endDate = newValue;
68
+ this.startDate = end.toISODate();
69
+ }
70
+ }
71
+ else {
72
+ if (type === 'start')
73
+ this.startDate = newValue;
74
+ else
75
+ this.endDate = newValue;
76
+ }
77
+ this.fireCustomEvent(CustomEventType.DateRangeChanged, {
78
+ start: this.startDate,
79
+ end: this.endDate,
80
+ range: this.selectedRange
81
+ });
82
+ }
83
+ canNavigatePrevious() {
84
+ if (this.selectedRange === 'ALL')
85
+ return false;
86
+ const currentStart = DateTime.fromISO(this.startDate);
87
+ let previousStart;
88
+ if (this.selectedRange === 'W') {
89
+ previousStart = currentStart.minus({ weeks: 1 });
90
+ }
91
+ else if (this.selectedRange === 'M') {
92
+ previousStart = currentStart.minus({ months: 1 });
93
+ }
94
+ else if (this.selectedRange === 'Y') {
95
+ previousStart = currentStart.minus({ years: 1 });
96
+ }
97
+ else if (this.selectedRange === '') {
98
+ // Custom range - determine the interval and navigate by that amount
99
+ const interval = this.getCustomRangeInterval();
100
+ if (interval.type === 'days') {
101
+ previousStart = currentStart.minus({ days: interval.amount });
102
+ }
103
+ else if (interval.type === 'months') {
104
+ previousStart = currentStart.minus({ months: interval.amount });
105
+ }
106
+ else if (interval.type === 'years') {
107
+ previousStart = currentStart.minus({ years: interval.amount });
108
+ }
109
+ else {
110
+ return false;
111
+ }
112
+ }
113
+ else {
114
+ return false;
115
+ }
116
+ return previousStart.toISODate() >= this.minDate;
117
+ }
118
+ canNavigateNext() {
119
+ if (this.selectedRange === 'ALL')
120
+ return false;
121
+ const currentEnd = DateTime.fromISO(this.endDate);
122
+ let nextEnd;
123
+ if (this.selectedRange === 'W') {
124
+ nextEnd = currentEnd.plus({ weeks: 1 });
125
+ }
126
+ else if (this.selectedRange === 'M') {
127
+ nextEnd = currentEnd.plus({ months: 1 });
128
+ }
129
+ else if (this.selectedRange === 'Y') {
130
+ nextEnd = currentEnd.plus({ years: 1 });
131
+ }
132
+ else if (this.selectedRange === '') {
133
+ // Custom range - determine the interval and navigate by that amount
134
+ const interval = this.getCustomRangeInterval();
135
+ if (interval.type === 'days') {
136
+ nextEnd = currentEnd.plus({ days: interval.amount });
137
+ }
138
+ else if (interval.type === 'months') {
139
+ nextEnd = currentEnd.plus({ months: interval.amount });
140
+ }
141
+ else if (interval.type === 'years') {
142
+ nextEnd = currentEnd.plus({ years: interval.amount });
143
+ }
144
+ else {
145
+ return false;
146
+ }
147
+ }
148
+ else {
149
+ return false;
150
+ }
151
+ return nextEnd.toISODate() <= this.maxDate;
152
+ }
153
+ getCustomRangeInterval() {
154
+ const start = DateTime.fromISO(this.startDate);
155
+ const end = DateTime.fromISO(this.endDate);
156
+ if (!start.isValid || !end.isValid) {
157
+ return { type: 'days', amount: 1 };
158
+ }
159
+ // Check if it's a complete month (first day to last day of any month)
160
+ const isLastDayOfMonth = end.day === end.daysInMonth;
161
+ if (start.day === 1 && isLastDayOfMonth) {
162
+ // Single complete month
163
+ if (start.month === end.month && start.year === end.year) {
164
+ return { type: 'months', amount: 1 };
165
+ }
166
+ // Multiple complete months - check if we span complete months only
167
+ const startOfFirstMonth = start.startOf('month');
168
+ const endOfLastMonth = end.endOf('month');
169
+ const monthsDiff = endOfLastMonth.diff(startOfFirstMonth, 'months').months + 1;
170
+ if (monthsDiff > 0 && Number.isInteger(monthsDiff)) {
171
+ return { type: 'months', amount: Math.round(monthsDiff) };
172
+ }
173
+ }
174
+ // Check if it's a full year
175
+ if (start.month === 1 &&
176
+ start.day === 1 &&
177
+ end.month === 12 &&
178
+ end.day === 31) {
179
+ // Single complete year
180
+ if (start.year === end.year) {
181
+ return { type: 'years', amount: 1 };
182
+ }
183
+ // Multiple complete years
184
+ const yearsDiff = end.year - start.year + 1;
185
+ if (yearsDiff > 0) {
186
+ return { type: 'years', amount: yearsDiff };
187
+ }
188
+ }
189
+ // Default to days for any other custom range
190
+ const daysDiff = end.diff(start, 'days').days + 1; // +1 to include both start and end days
191
+ return { type: 'days', amount: Math.max(1, Math.round(daysDiff)) };
192
+ }
193
+ navigatePrevious() {
194
+ if (!this.canNavigatePrevious())
195
+ return;
196
+ const currentStart = DateTime.fromISO(this.startDate);
197
+ const currentEnd = DateTime.fromISO(this.endDate);
198
+ let newStart;
199
+ let newEnd;
200
+ if (this.selectedRange === 'W') {
201
+ newStart = currentStart.minus({ weeks: 1 });
202
+ newEnd = currentEnd.minus({ weeks: 1 });
203
+ }
204
+ else if (this.selectedRange === 'M') {
205
+ // Check if current M range is a complete month, if so maintain month boundaries
206
+ const interval = this.getCustomRangeInterval();
207
+ if (interval.type === 'months') {
208
+ newStart = currentStart.minus({ months: 1 }).startOf('month');
209
+ newEnd = newStart
210
+ .plus({ months: interval.amount })
211
+ .minus({ days: 1 })
212
+ .endOf('day');
213
+ }
214
+ else {
215
+ newStart = currentStart.minus({ months: 1 });
216
+ newEnd = currentEnd.minus({ months: 1 });
217
+ }
218
+ }
219
+ else if (this.selectedRange === 'Y') {
220
+ newStart = currentStart.minus({ years: 1 });
221
+ newEnd = currentEnd.minus({ years: 1 });
222
+ }
223
+ else if (this.selectedRange === '') {
224
+ // Custom range - determine the interval and navigate by that amount
225
+ const interval = this.getCustomRangeInterval();
226
+ if (interval.type === 'days') {
227
+ newStart = currentStart.minus({ days: interval.amount });
228
+ newEnd = currentEnd.minus({ days: interval.amount });
229
+ }
230
+ else if (interval.type === 'months') {
231
+ // For month navigation, maintain complete month boundaries
232
+ newStart = currentStart
233
+ .minus({ months: interval.amount })
234
+ .startOf('month');
235
+ newEnd = newStart
236
+ .plus({ months: interval.amount })
237
+ .minus({ days: 1 })
238
+ .endOf('day');
239
+ }
240
+ else if (interval.type === 'years') {
241
+ newStart = currentStart.minus({ years: interval.amount });
242
+ newEnd = currentEnd.minus({ years: interval.amount });
243
+ }
244
+ else {
245
+ return;
246
+ }
247
+ }
248
+ else {
249
+ return;
250
+ }
251
+ // Enforce min/max bounds
252
+ const minDateTime = DateTime.fromISO(this.minDate);
253
+ const maxDateTime = DateTime.fromISO(this.maxDate);
254
+ const startDate = newStart < minDateTime ? this.minDate : newStart.toISODate();
255
+ const endDate = newEnd > maxDateTime ? this.maxDate : newEnd.toISODate();
256
+ this.startDate = startDate;
257
+ this.endDate = endDate;
258
+ this.fireCustomEvent(CustomEventType.DateRangeChanged, {
259
+ start: this.startDate,
260
+ end: this.endDate,
261
+ range: this.selectedRange
262
+ });
263
+ }
264
+ navigateNext() {
265
+ if (!this.canNavigateNext())
266
+ return;
267
+ const currentStart = DateTime.fromISO(this.startDate);
268
+ const currentEnd = DateTime.fromISO(this.endDate);
269
+ let newStart;
270
+ let newEnd;
271
+ if (this.selectedRange === 'W') {
272
+ newStart = currentStart.plus({ weeks: 1 });
273
+ newEnd = currentEnd.plus({ weeks: 1 });
274
+ }
275
+ else if (this.selectedRange === 'M') {
276
+ // Check if current M range is a complete month, if so maintain month boundaries
277
+ const interval = this.getCustomRangeInterval();
278
+ if (interval.type === 'months') {
279
+ newStart = currentStart.plus({ months: 1 }).startOf('month');
280
+ newEnd = newStart
281
+ .plus({ months: interval.amount })
282
+ .minus({ days: 1 })
283
+ .endOf('day');
284
+ }
285
+ else {
286
+ newStart = currentStart.plus({ months: 1 });
287
+ newEnd = currentEnd.plus({ months: 1 });
288
+ }
289
+ }
290
+ else if (this.selectedRange === 'Y') {
291
+ newStart = currentStart.plus({ years: 1 });
292
+ newEnd = currentEnd.plus({ years: 1 });
293
+ }
294
+ else if (this.selectedRange === '') {
295
+ // Custom range - determine the interval and navigate by that amount
296
+ const interval = this.getCustomRangeInterval();
297
+ if (interval.type === 'days') {
298
+ newStart = currentStart.plus({ days: interval.amount });
299
+ newEnd = currentEnd.plus({ days: interval.amount });
300
+ }
301
+ else if (interval.type === 'months') {
302
+ // For month navigation, maintain complete month boundaries
303
+ newStart = currentStart
304
+ .plus({ months: interval.amount })
305
+ .startOf('month');
306
+ newEnd = newStart
307
+ .plus({ months: interval.amount })
308
+ .minus({ days: 1 })
309
+ .endOf('day');
310
+ }
311
+ else if (interval.type === 'years') {
312
+ newStart = currentStart.plus({ years: interval.amount });
313
+ newEnd = currentEnd.plus({ years: interval.amount });
314
+ }
315
+ else {
316
+ return;
317
+ }
318
+ }
319
+ else {
320
+ return;
321
+ }
322
+ // Enforce min/max bounds
323
+ const minDateTime = DateTime.fromISO(this.minDate);
324
+ const maxDateTime = DateTime.fromISO(this.maxDate);
325
+ const startDate = newStart < minDateTime ? this.minDate : newStart.toISODate();
326
+ const endDate = newEnd > maxDateTime ? this.maxDate : newEnd.toISODate();
327
+ this.startDate = startDate;
328
+ this.endDate = endDate;
329
+ this.fireCustomEvent(CustomEventType.DateRangeChanged, {
330
+ start: this.startDate,
331
+ end: this.endDate,
332
+ range: this.selectedRange
333
+ });
334
+ }
335
+ getNavigationLabel(direction) {
336
+ const interval = this.getCustomRangeInterval();
337
+ const amount = interval.amount;
338
+ const unit = interval.type === 'days'
339
+ ? amount === 1
340
+ ? 'day'
341
+ : 'days'
342
+ : interval.type === 'months'
343
+ ? amount === 1
344
+ ? 'month'
345
+ : 'months'
346
+ : amount === 1
347
+ ? 'year'
348
+ : 'years';
349
+ return `${direction === 'previous' ? 'Previous' : 'Next'} ${amount} ${unit}`;
350
+ }
351
+ updated(changed) {
352
+ super.updated(changed);
353
+ if ((changed.has('startDate') && changed.has('endDate') && !this.startDate) ||
354
+ !this.endDate) {
355
+ this.setRange('M');
356
+ }
357
+ if (changed.has('editingStart') && this.editingStart) {
358
+ setTimeout(() => {
359
+ var _a;
360
+ const startPicker = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('temba-datepicker.start-picker');
361
+ if (startPicker) {
362
+ startPicker.handleClicked();
363
+ }
364
+ }, 0);
365
+ }
366
+ if (changed.has('editingEnd') && this.editingEnd) {
367
+ setTimeout(() => {
368
+ var _a;
369
+ const endPicker = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('temba-datepicker.end-picker');
370
+ if (endPicker) {
371
+ endPicker.handleClicked();
372
+ }
373
+ }, 0);
374
+ }
375
+ }
376
+ render() {
377
+ return html `
378
+ <div class="range-container">
379
+ ${this.editingStart
380
+ ? html `<temba-datepicker
381
+ class="start-picker"
382
+ .value=${this.startDate}
383
+ .min=${this.minDate}
384
+ .max=${this.maxDate}
385
+ @change=${(e) => {
386
+ const value = e.target.value;
387
+ this.setValidRange('start', value);
388
+ this.editingStart = false;
389
+ this.selectedRange = '';
390
+ }}
391
+ @blur=${() => (this.editingStart = false)}
392
+ ></temba-datepicker>`
393
+ : html `<span class="date-display" @click=${this.handleStartClick}
394
+ >${this.startDate || 'Start date'}</span
395
+ >`}
396
+ <span> - </span>
397
+ ${this.editingEnd
398
+ ? html `<temba-datepicker
399
+ .value=${this.endDate}
400
+ class="end-picker"
401
+ .min=${this.minDate}
402
+ .max=${this.maxDate}
403
+ @change=${(e) => {
404
+ const value = e.target.value;
405
+ this.setValidRange('end', value);
406
+ this.editingEnd = false;
407
+ this.selectedRange = '';
408
+ }}
409
+ @blur=${() => (this.editingEnd = false)}
410
+ ></temba-datepicker>`
411
+ : html `<span class="date-display" @click=${this.handleEndClick}
412
+ >${this.endDate || 'End date'}</span
413
+ >`}
414
+ <div class="navigation-container">
415
+ <button
416
+ class="nav-arrow ${this.selectedRange === 'ALL' ? 'hidden' : ''}"
417
+ ?disabled=${!this.canNavigatePrevious()}
418
+ @click=${this.navigatePrevious}
419
+ title="Previous ${this.selectedRange === 'W'
420
+ ? 'week'
421
+ : this.selectedRange === 'M'
422
+ ? 'month'
423
+ : this.selectedRange === 'Y'
424
+ ? 'year'
425
+ : this.selectedRange === ''
426
+ ? this.getNavigationLabel('previous')
427
+ : 'period'}"
428
+ >
429
+
430
+ </button>
431
+ <div class="button-group">
432
+ <button
433
+ class="range-btn ${this.selectedRange === 'W' ? 'selected' : ''}"
434
+ @click=${() => this.setRange('W')}
435
+ >
436
+ W
437
+ </button>
438
+ <button
439
+ class="range-btn ${this.selectedRange === 'M' ? 'selected' : ''}"
440
+ @click=${() => this.setRange('M')}
441
+ >
442
+ M
443
+ </button>
444
+ <button
445
+ class="range-btn ${this.selectedRange === 'Y' ? 'selected' : ''}"
446
+ @click=${() => this.setRange('Y')}
447
+ >
448
+ Y
449
+ </button>
450
+ <button
451
+ class="range-btn ${this.selectedRange === 'ALL'
452
+ ? 'selected'
453
+ : ''}"
454
+ @click=${() => this.setRange('ALL')}
455
+ >
456
+ All
457
+ </button>
458
+ </div>
459
+ <button
460
+ class="nav-arrow ${this.selectedRange === 'ALL' ? 'hidden' : ''}"
461
+ ?disabled=${!this.canNavigateNext()}
462
+ @click=${this.navigateNext}
463
+ title="Next ${this.selectedRange === 'W'
464
+ ? 'week'
465
+ : this.selectedRange === 'M'
466
+ ? 'month'
467
+ : this.selectedRange === 'Y'
468
+ ? 'year'
469
+ : this.selectedRange === ''
470
+ ? this.getNavigationLabel('next')
471
+ : 'period'}"
472
+ >
473
+
474
+ </button>
475
+ </div>
476
+ </div>
477
+ `;
478
+ }
479
+ }
480
+ RangePicker.styles = css `
481
+ .range-container {
482
+ display: flex;
483
+ gap: 0.5em;
484
+ align-items: center;
485
+ }
486
+ .date-display {
487
+ cursor: pointer;
488
+ padding: 0.2em 0.5em;
489
+ margin: 0.6em 0;
490
+ border-radius: 4px;
491
+ border: 1px solid transparent;
492
+ transition: border 0.2s;
493
+ }
494
+
495
+ .date-display:hover {
496
+ border: 1px solid var(--color-widget-border, #bbb);
497
+ background: var(--color-widget-hover, #f5f5f5);
498
+ }
499
+
500
+ input[type='date'] {
501
+ font-size: 1em;
502
+ padding: 0.2em 0.5em;
503
+ border-radius: 4px;
504
+ border: 1px solid #bbb;
505
+ }
506
+
507
+ .navigation-container {
508
+ display: flex;
509
+ align-items: center;
510
+ gap: 0.25em;
511
+ }
512
+
513
+ .nav-arrow {
514
+ background: #f5f5f5;
515
+ border: 1px solid #bbb;
516
+
517
+ border-radius: var(--curvature);
518
+ padding: 0em 0em;
519
+ cursor: pointer;
520
+ font-size: 0.6em;
521
+ display: flex;
522
+ align-items: center;
523
+ justify-content: center;
524
+ width: 23px;
525
+ height: 23px;
526
+ transition: background 0.2s, border 0.2s, opacity 0.2s;
527
+ }
528
+
529
+ .nav-arrow:hover:not(:disabled) {
530
+ background: #e0eaff;
531
+ border-color: #3399ff;
532
+ }
533
+
534
+ .nav-arrow:disabled {
535
+ opacity: 0.5;
536
+ cursor: not-allowed;
537
+ background: #f9f9f9;
538
+ }
539
+
540
+ .nav-arrow.hidden {
541
+ visibility: hidden;
542
+ }
543
+
544
+ .button-group {
545
+ display: flex;
546
+ margin-left: 0em;
547
+ }
548
+ .range-btn {
549
+ background: #f5f5f5;
550
+ border: 1px solid #bbb;
551
+ border-radius: 0px;
552
+ margin-left: -1px;
553
+ padding: 0.2em 0.8em;
554
+ cursor: pointer;
555
+ font-size: 0.95em;
556
+ transition: background 0.2s, border 0.2s;
557
+ }
558
+
559
+ .button-group .range-btn:first-child {
560
+ border-radius: 4px 0 0 4px;
561
+ }
562
+
563
+ .button-group .range-btn:last-child {
564
+ border-radius: 0 4px 4px 0;
565
+ }
566
+
567
+ .range-btn.selected,
568
+ .range-btn:active {
569
+ background: #e0eaff;
570
+ border-color: #3399ff;
571
+ }
572
+ `;
573
+ __decorate([
574
+ property({ type: String, attribute: 'start' })
575
+ ], RangePicker.prototype, "startDate", void 0);
576
+ __decorate([
577
+ property({ type: String, attribute: 'end' })
578
+ ], RangePicker.prototype, "endDate", void 0);
579
+ __decorate([
580
+ property({ type: Boolean })
581
+ ], RangePicker.prototype, "editingStart", void 0);
582
+ __decorate([
583
+ property({ type: Boolean })
584
+ ], RangePicker.prototype, "editingEnd", void 0);
585
+ __decorate([
586
+ property({ type: String })
587
+ ], RangePicker.prototype, "selectedRange", void 0);
588
+ __decorate([
589
+ property({ type: String, attribute: 'min' })
590
+ ], RangePicker.prototype, "minDate", void 0);
591
+ __decorate([
592
+ property({ type: String, attribute: 'max' })
593
+ ], RangePicker.prototype, "maxDate", void 0);
594
+ customElements.define('temba-range-picker', RangePicker);
595
+ //# sourceMappingURL=RangePicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RangePicker.js","sourceRoot":"","sources":["../../../src/datepicker/RangePicker.ts"],"names":[],"mappings":"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","sourcesContent":["import { property } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { DateTime } from 'luxon';\nimport { html, css } from 'lit';\nimport { DatePicker } from './DatePicker';\nimport { CustomEventType } from '../interfaces';\n\nexport class RangePicker extends RapidElement {\n static styles = css`\n .range-container {\n display: flex;\n gap: 0.5em;\n align-items: center;\n }\n .date-display {\n cursor: pointer;\n padding: 0.2em 0.5em;\n margin: 0.6em 0;\n border-radius: 4px;\n border: 1px solid transparent;\n transition: border 0.2s;\n }\n\n .date-display:hover {\n border: 1px solid var(--color-widget-border, #bbb);\n background: var(--color-widget-hover, #f5f5f5);\n }\n\n input[type='date'] {\n font-size: 1em;\n padding: 0.2em 0.5em;\n border-radius: 4px;\n border: 1px solid #bbb;\n }\n\n .navigation-container {\n display: flex;\n align-items: center;\n gap: 0.25em;\n }\n\n .nav-arrow {\n background: #f5f5f5;\n border: 1px solid #bbb;\n\n border-radius: var(--curvature);\n padding: 0em 0em;\n cursor: pointer;\n font-size: 0.6em;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 23px;\n height: 23px;\n transition: background 0.2s, border 0.2s, opacity 0.2s;\n }\n\n .nav-arrow:hover:not(:disabled) {\n background: #e0eaff;\n border-color: #3399ff;\n }\n\n .nav-arrow:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n background: #f9f9f9;\n }\n\n .nav-arrow.hidden {\n visibility: hidden;\n }\n\n .button-group {\n display: flex;\n margin-left: 0em;\n }\n .range-btn {\n background: #f5f5f5;\n border: 1px solid #bbb;\n border-radius: 0px;\n margin-left: -1px;\n padding: 0.2em 0.8em;\n cursor: pointer;\n font-size: 0.95em;\n transition: background 0.2s, border 0.2s;\n }\n\n .button-group .range-btn:first-child {\n border-radius: 4px 0 0 4px;\n }\n\n .button-group .range-btn:last-child {\n border-radius: 0 4px 4px 0;\n }\n\n .range-btn.selected,\n .range-btn:active {\n background: #e0eaff;\n border-color: #3399ff;\n }\n `;\n\n @property({ type: String, attribute: 'start' })\n startDate = '';\n\n @property({ type: String, attribute: 'end' })\n endDate = '';\n\n @property({ type: Boolean })\n editingStart = false;\n\n @property({ type: Boolean })\n editingEnd = false;\n\n @property({ type: String })\n selectedRange: 'W' | 'M' | 'Y' | 'ALL' | '' = '';\n\n @property({ type: String, attribute: 'min' })\n minDate = '2012-01-01';\n\n @property({ type: String, attribute: 'max' })\n maxDate = DateTime.now().toISODate();\n\n private handleStartClick() {\n this.editingStart = true;\n }\n\n private handleEndClick() {\n this.editingEnd = true;\n }\n\n private setRange(type: 'W' | 'M' | 'Y' | 'ALL') {\n const today = DateTime.now().toISODate();\n let start = '';\n if (type === 'W') {\n start = DateTime.now().minus({ days: 6 }).toISODate();\n } else if (type === 'M') {\n start = DateTime.now().minus({ months: 1 }).plus({ days: 1 }).toISODate();\n } else if (type === 'Y') {\n start = DateTime.now().minus({ years: 1 }).plus({ days: 1 }).toISODate();\n } else if (type === 'ALL') {\n start = this.minDate || '2012-01-01';\n }\n this.startDate = start;\n this.endDate = today;\n this.selectedRange = type;\n this.editingStart = false;\n this.editingEnd = false;\n\n this.fireCustomEvent(CustomEventType.DateRangeChanged, {\n start: this.startDate,\n end: this.endDate,\n range: this.selectedRange\n });\n }\n\n private setValidRange(type: 'start' | 'end', value: string) {\n // Enforce min/max\n let newValue = value;\n if (newValue < this.minDate) newValue = this.minDate;\n if (newValue > this.maxDate) newValue = this.maxDate;\n const start = DateTime.fromISO(\n type === 'start' ? newValue : this.startDate\n );\n const end = DateTime.fromISO(type === 'end' ? newValue : this.endDate);\n\n if (!start.isValid || !end.isValid) return;\n if (start > end) {\n if (type === 'start') {\n this.startDate = newValue;\n this.endDate = start.toISODate();\n } else {\n this.endDate = newValue;\n this.startDate = end.toISODate();\n }\n } else {\n if (type === 'start') this.startDate = newValue;\n else this.endDate = newValue;\n }\n\n this.fireCustomEvent(CustomEventType.DateRangeChanged, {\n start: this.startDate,\n end: this.endDate,\n range: this.selectedRange\n });\n }\n\n private canNavigatePrevious(): boolean {\n if (this.selectedRange === 'ALL') return false;\n\n const currentStart = DateTime.fromISO(this.startDate);\n let previousStart: DateTime;\n\n if (this.selectedRange === 'W') {\n previousStart = currentStart.minus({ weeks: 1 });\n } else if (this.selectedRange === 'M') {\n previousStart = currentStart.minus({ months: 1 });\n } else if (this.selectedRange === 'Y') {\n previousStart = currentStart.minus({ years: 1 });\n } else if (this.selectedRange === '') {\n // Custom range - determine the interval and navigate by that amount\n const interval = this.getCustomRangeInterval();\n if (interval.type === 'days') {\n previousStart = currentStart.minus({ days: interval.amount });\n } else if (interval.type === 'months') {\n previousStart = currentStart.minus({ months: interval.amount });\n } else if (interval.type === 'years') {\n previousStart = currentStart.minus({ years: interval.amount });\n } else {\n return false;\n }\n } else {\n return false;\n }\n\n return previousStart.toISODate() >= this.minDate;\n }\n\n private canNavigateNext(): boolean {\n if (this.selectedRange === 'ALL') return false;\n\n const currentEnd = DateTime.fromISO(this.endDate);\n let nextEnd: DateTime;\n\n if (this.selectedRange === 'W') {\n nextEnd = currentEnd.plus({ weeks: 1 });\n } else if (this.selectedRange === 'M') {\n nextEnd = currentEnd.plus({ months: 1 });\n } else if (this.selectedRange === 'Y') {\n nextEnd = currentEnd.plus({ years: 1 });\n } else if (this.selectedRange === '') {\n // Custom range - determine the interval and navigate by that amount\n const interval = this.getCustomRangeInterval();\n if (interval.type === 'days') {\n nextEnd = currentEnd.plus({ days: interval.amount });\n } else if (interval.type === 'months') {\n nextEnd = currentEnd.plus({ months: interval.amount });\n } else if (interval.type === 'years') {\n nextEnd = currentEnd.plus({ years: interval.amount });\n } else {\n return false;\n }\n } else {\n return false;\n }\n\n return nextEnd.toISODate() <= this.maxDate;\n }\n\n private getCustomRangeInterval(): {\n type: 'days' | 'months' | 'years';\n amount: number;\n } {\n const start = DateTime.fromISO(this.startDate);\n const end = DateTime.fromISO(this.endDate);\n\n if (!start.isValid || !end.isValid) {\n return { type: 'days', amount: 1 };\n }\n\n // Check if it's a complete month (first day to last day of any month)\n const isLastDayOfMonth = end.day === end.daysInMonth;\n if (start.day === 1 && isLastDayOfMonth) {\n // Single complete month\n if (start.month === end.month && start.year === end.year) {\n return { type: 'months', amount: 1 };\n }\n\n // Multiple complete months - check if we span complete months only\n const startOfFirstMonth = start.startOf('month');\n const endOfLastMonth = end.endOf('month');\n const monthsDiff =\n endOfLastMonth.diff(startOfFirstMonth, 'months').months + 1;\n\n if (monthsDiff > 0 && Number.isInteger(monthsDiff)) {\n return { type: 'months', amount: Math.round(monthsDiff) };\n }\n }\n\n // Check if it's a full year\n if (\n start.month === 1 &&\n start.day === 1 &&\n end.month === 12 &&\n end.day === 31\n ) {\n // Single complete year\n if (start.year === end.year) {\n return { type: 'years', amount: 1 };\n }\n\n // Multiple complete years\n const yearsDiff = end.year - start.year + 1;\n if (yearsDiff > 0) {\n return { type: 'years', amount: yearsDiff };\n }\n }\n\n // Default to days for any other custom range\n const daysDiff = end.diff(start, 'days').days + 1; // +1 to include both start and end days\n return { type: 'days', amount: Math.max(1, Math.round(daysDiff)) };\n }\n\n private navigatePrevious() {\n if (!this.canNavigatePrevious()) return;\n\n const currentStart = DateTime.fromISO(this.startDate);\n const currentEnd = DateTime.fromISO(this.endDate);\n let newStart: DateTime;\n let newEnd: DateTime;\n\n if (this.selectedRange === 'W') {\n newStart = currentStart.minus({ weeks: 1 });\n newEnd = currentEnd.minus({ weeks: 1 });\n } else if (this.selectedRange === 'M') {\n // Check if current M range is a complete month, if so maintain month boundaries\n const interval = this.getCustomRangeInterval();\n if (interval.type === 'months') {\n newStart = currentStart.minus({ months: 1 }).startOf('month');\n newEnd = newStart\n .plus({ months: interval.amount })\n .minus({ days: 1 })\n .endOf('day');\n } else {\n newStart = currentStart.minus({ months: 1 });\n newEnd = currentEnd.minus({ months: 1 });\n }\n } else if (this.selectedRange === 'Y') {\n newStart = currentStart.minus({ years: 1 });\n newEnd = currentEnd.minus({ years: 1 });\n } else if (this.selectedRange === '') {\n // Custom range - determine the interval and navigate by that amount\n const interval = this.getCustomRangeInterval();\n if (interval.type === 'days') {\n newStart = currentStart.minus({ days: interval.amount });\n newEnd = currentEnd.minus({ days: interval.amount });\n } else if (interval.type === 'months') {\n // For month navigation, maintain complete month boundaries\n newStart = currentStart\n .minus({ months: interval.amount })\n .startOf('month');\n newEnd = newStart\n .plus({ months: interval.amount })\n .minus({ days: 1 })\n .endOf('day');\n } else if (interval.type === 'years') {\n newStart = currentStart.minus({ years: interval.amount });\n newEnd = currentEnd.minus({ years: interval.amount });\n } else {\n return;\n }\n } else {\n return;\n }\n\n // Enforce min/max bounds\n const minDateTime = DateTime.fromISO(this.minDate);\n const maxDateTime = DateTime.fromISO(this.maxDate);\n const startDate =\n newStart < minDateTime ? this.minDate : newStart.toISODate();\n const endDate = newEnd > maxDateTime ? this.maxDate : newEnd.toISODate();\n\n this.startDate = startDate;\n this.endDate = endDate;\n\n this.fireCustomEvent(CustomEventType.DateRangeChanged, {\n start: this.startDate,\n end: this.endDate,\n range: this.selectedRange\n });\n }\n\n private navigateNext() {\n if (!this.canNavigateNext()) return;\n\n const currentStart = DateTime.fromISO(this.startDate);\n const currentEnd = DateTime.fromISO(this.endDate);\n let newStart: DateTime;\n let newEnd: DateTime;\n\n if (this.selectedRange === 'W') {\n newStart = currentStart.plus({ weeks: 1 });\n newEnd = currentEnd.plus({ weeks: 1 });\n } else if (this.selectedRange === 'M') {\n // Check if current M range is a complete month, if so maintain month boundaries\n const interval = this.getCustomRangeInterval();\n if (interval.type === 'months') {\n newStart = currentStart.plus({ months: 1 }).startOf('month');\n newEnd = newStart\n .plus({ months: interval.amount })\n .minus({ days: 1 })\n .endOf('day');\n } else {\n newStart = currentStart.plus({ months: 1 });\n newEnd = currentEnd.plus({ months: 1 });\n }\n } else if (this.selectedRange === 'Y') {\n newStart = currentStart.plus({ years: 1 });\n newEnd = currentEnd.plus({ years: 1 });\n } else if (this.selectedRange === '') {\n // Custom range - determine the interval and navigate by that amount\n const interval = this.getCustomRangeInterval();\n if (interval.type === 'days') {\n newStart = currentStart.plus({ days: interval.amount });\n newEnd = currentEnd.plus({ days: interval.amount });\n } else if (interval.type === 'months') {\n // For month navigation, maintain complete month boundaries\n newStart = currentStart\n .plus({ months: interval.amount })\n .startOf('month');\n newEnd = newStart\n .plus({ months: interval.amount })\n .minus({ days: 1 })\n .endOf('day');\n } else if (interval.type === 'years') {\n newStart = currentStart.plus({ years: interval.amount });\n newEnd = currentEnd.plus({ years: interval.amount });\n } else {\n return;\n }\n } else {\n return;\n }\n\n // Enforce min/max bounds\n const minDateTime = DateTime.fromISO(this.minDate);\n const maxDateTime = DateTime.fromISO(this.maxDate);\n const startDate =\n newStart < minDateTime ? this.minDate : newStart.toISODate();\n const endDate = newEnd > maxDateTime ? this.maxDate : newEnd.toISODate();\n\n this.startDate = startDate;\n this.endDate = endDate;\n\n this.fireCustomEvent(CustomEventType.DateRangeChanged, {\n start: this.startDate,\n end: this.endDate,\n range: this.selectedRange\n });\n }\n\n private getNavigationLabel(direction: 'previous' | 'next'): string {\n const interval = this.getCustomRangeInterval();\n const amount = interval.amount;\n const unit =\n interval.type === 'days'\n ? amount === 1\n ? 'day'\n : 'days'\n : interval.type === 'months'\n ? amount === 1\n ? 'month'\n : 'months'\n : amount === 1\n ? 'year'\n : 'years';\n\n return `${\n direction === 'previous' ? 'Previous' : 'Next'\n } ${amount} ${unit}`;\n }\n\n updated(changed: Map<string, any>) {\n super.updated(changed);\n\n if (\n (changed.has('startDate') && changed.has('endDate') && !this.startDate) ||\n !this.endDate\n ) {\n this.setRange('M');\n }\n\n if (changed.has('editingStart') && this.editingStart) {\n setTimeout(() => {\n const startPicker: DatePicker = this.shadowRoot?.querySelector(\n 'temba-datepicker.start-picker'\n );\n\n if (startPicker) {\n startPicker.handleClicked();\n }\n }, 0);\n }\n\n if (changed.has('editingEnd') && this.editingEnd) {\n setTimeout(() => {\n const endPicker: DatePicker = this.shadowRoot?.querySelector(\n 'temba-datepicker.end-picker'\n );\n if (endPicker) {\n endPicker.handleClicked();\n }\n }, 0);\n }\n }\n\n render() {\n return html`\n <div class=\"range-container\">\n ${this.editingStart\n ? html`<temba-datepicker\n class=\"start-picker\"\n .value=${this.startDate}\n .min=${this.minDate}\n .max=${this.maxDate}\n @change=${(e: Event) => {\n const value = (e.target as any).value;\n this.setValidRange('start', value);\n this.editingStart = false;\n this.selectedRange = '';\n }}\n @blur=${() => (this.editingStart = false)}\n ></temba-datepicker>`\n : html`<span class=\"date-display\" @click=${this.handleStartClick}\n >${this.startDate || 'Start date'}</span\n >`}\n <span> - </span>\n ${this.editingEnd\n ? html`<temba-datepicker\n .value=${this.endDate}\n class=\"end-picker\"\n .min=${this.minDate}\n .max=${this.maxDate}\n @change=${(e: Event) => {\n const value = (e.target as any).value;\n this.setValidRange('end', value);\n this.editingEnd = false;\n this.selectedRange = '';\n }}\n @blur=${() => (this.editingEnd = false)}\n ></temba-datepicker>`\n : html`<span class=\"date-display\" @click=${this.handleEndClick}\n >${this.endDate || 'End date'}</span\n >`}\n <div class=\"navigation-container\">\n <button\n class=\"nav-arrow ${this.selectedRange === 'ALL' ? 'hidden' : ''}\"\n ?disabled=${!this.canNavigatePrevious()}\n @click=${this.navigatePrevious}\n title=\"Previous ${this.selectedRange === 'W'\n ? 'week'\n : this.selectedRange === 'M'\n ? 'month'\n : this.selectedRange === 'Y'\n ? 'year'\n : this.selectedRange === ''\n ? this.getNavigationLabel('previous')\n : 'period'}\"\n >\n ◀\n </button>\n <div class=\"button-group\">\n <button\n class=\"range-btn ${this.selectedRange === 'W' ? 'selected' : ''}\"\n @click=${() => this.setRange('W')}\n >\n W\n </button>\n <button\n class=\"range-btn ${this.selectedRange === 'M' ? 'selected' : ''}\"\n @click=${() => this.setRange('M')}\n >\n M\n </button>\n <button\n class=\"range-btn ${this.selectedRange === 'Y' ? 'selected' : ''}\"\n @click=${() => this.setRange('Y')}\n >\n Y\n </button>\n <button\n class=\"range-btn ${this.selectedRange === 'ALL'\n ? 'selected'\n : ''}\"\n @click=${() => this.setRange('ALL')}\n >\n All\n </button>\n </div>\n <button\n class=\"nav-arrow ${this.selectedRange === 'ALL' ? 'hidden' : ''}\"\n ?disabled=${!this.canNavigateNext()}\n @click=${this.navigateNext}\n title=\"Next ${this.selectedRange === 'W'\n ? 'week'\n : this.selectedRange === 'M'\n ? 'month'\n : this.selectedRange === 'Y'\n ? 'year'\n : this.selectedRange === ''\n ? this.getNavigationLabel('next')\n : 'period'}\"\n >\n ▶\n </button>\n </div>\n </div>\n `;\n }\n}\n\ncustomElements.define('temba-range-picker', RangePicker);\n"]}