@triptease/tt-calendar 6.1.1 → 6.2.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.
- package/dist/cjs/src/DateSelectionContext.js +40 -0
- package/dist/cjs/src/DateSelectionContext.js.map +1 -0
- package/dist/cjs/src/Styles.js +267 -0
- package/dist/cjs/src/Styles.js.map +1 -0
- package/dist/cjs/src/TtCalendar.js +480 -0
- package/dist/cjs/src/TtCalendar.js.map +1 -0
- package/dist/cjs/src/helpers.js +9 -0
- package/dist/cjs/src/helpers.js.map +1 -0
- package/dist/cjs/src/index.js +6 -0
- package/dist/cjs/src/index.js.map +1 -0
- package/dist/cjs/src/tt-calendar.js +11 -0
- package/dist/cjs/src/tt-calendar.js.map +1 -0
- package/dist/esm/src/TtCalendar.d.ts +10 -1
- package/dist/esm/src/TtCalendar.js +114 -69
- package/dist/esm/src/TtCalendar.js.map +1 -1
- package/dist/esm/test/tt-calendar.test.js +62 -0
- package/dist/esm/test/tt-calendar.test.js.map +1 -1
- package/package.json +6 -2
- package/CHANGELOG.md +0 -117
- package/custom-elements.json +0 -668
- package/demo/index.html +0 -23
- package/test/tt-calendar.test.ts +0 -255
- package/tsconfig.cjs.json +0 -9
- package/tsconfig.json +0 -9
package/test/tt-calendar.test.ts
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
import { elementUpdated, expect, fixture, html, oneEvent } from '@open-wc/testing';
|
|
2
|
-
import { DateTime, Settings } from 'luxon';
|
|
3
|
-
import '../src/tt-calendar.js'; // This handles the registration
|
|
4
|
-
import { Calendar } from '../src/TtCalendar.js';
|
|
5
|
-
|
|
6
|
-
describe('Calendar', () => {
|
|
7
|
-
describe('initialization', () => {
|
|
8
|
-
const originalNow = DateTime.now().toMillis();
|
|
9
|
-
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
Settings.defaultZone = 'system';
|
|
12
|
-
Settings.now = () => originalNow;
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('should render with default props', async () => {
|
|
16
|
-
const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);
|
|
17
|
-
expect(el).to.exist;
|
|
18
|
-
expect(el.range).to.be.false;
|
|
19
|
-
expect(el.value).to.be.undefined;
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {
|
|
23
|
-
it(`should render the correct days of the week in ${timezone} timezone`, async () => {
|
|
24
|
-
Settings.defaultZone = timezone;
|
|
25
|
-
const now = DateTime.local(2025, 6, 4, 22, 0, 0).toMillis();
|
|
26
|
-
Settings.now = () => now;
|
|
27
|
-
const today = DateTime.now().toISO()!;
|
|
28
|
-
const el = await fixture<Calendar>(html` <tt-calendar value="${today}"></tt-calendar>`);
|
|
29
|
-
|
|
30
|
-
const sunday = DateTime.fromISO(today).startOf('week').plus({ days: 6 }).toFormat('ccc');
|
|
31
|
-
|
|
32
|
-
const headers = el.shadowRoot!.querySelectorAll('th');
|
|
33
|
-
expect(headers[0].textContent?.trim()).to.equal(sunday);
|
|
34
|
-
|
|
35
|
-
const dayRows = el.shadowRoot!.querySelectorAll('tr');
|
|
36
|
-
const secondRowOfDays = dayRows[2].querySelectorAll('td');
|
|
37
|
-
|
|
38
|
-
expect(secondRowOfDays[0].textContent?.trim()).to.equal('8');
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe('visibility', () => {
|
|
44
|
-
xit('should toggle visibility when calling toggleVisibility', async () => {
|
|
45
|
-
const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);
|
|
46
|
-
|
|
47
|
-
expect(el).to.be.instanceOf(Calendar);
|
|
48
|
-
|
|
49
|
-
el.toggleVisibility();
|
|
50
|
-
await elementUpdated(el);
|
|
51
|
-
|
|
52
|
-
await expect(el.shadowRoot!.querySelector('[part="dialog"]')?.getAttribute('inert')).not.to.exist;
|
|
53
|
-
|
|
54
|
-
el.toggleVisibility();
|
|
55
|
-
await elementUpdated(el);
|
|
56
|
-
await expect(el.shadowRoot!.querySelector('[part="dialog"]')?.getAttribute('inert')).to.exist;
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
xit('should close on outside click', async () => {
|
|
60
|
-
const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);
|
|
61
|
-
el.toggleVisibility();
|
|
62
|
-
await elementUpdated(el);
|
|
63
|
-
|
|
64
|
-
const focusOutEvent = new FocusEvent('focusout', {
|
|
65
|
-
relatedTarget: document.body,
|
|
66
|
-
});
|
|
67
|
-
el.shadowRoot!.querySelector('[part="calendar"]')?.dispatchEvent(focusOutEvent);
|
|
68
|
-
await elementUpdated(el);
|
|
69
|
-
|
|
70
|
-
await expect(el.shadowRoot!.querySelector('[part="calendar"]')?.getAttribute('inert')).to.exist;
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
xit('should focus calendar div when opened', async () => {
|
|
74
|
-
const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);
|
|
75
|
-
el.toggleVisibility();
|
|
76
|
-
|
|
77
|
-
await elementUpdated(el);
|
|
78
|
-
|
|
79
|
-
const calendar = el.shadowRoot!.querySelector('[part="calendar"]');
|
|
80
|
-
expect(calendar).to.exist;
|
|
81
|
-
expect(el.shadowRoot!.activeElement === calendar).to.be.true;
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {
|
|
86
|
-
describe(`single date selection in ${timezone} timezone`, () => {
|
|
87
|
-
const originalNow = DateTime.now().toMillis();
|
|
88
|
-
|
|
89
|
-
afterEach(() => {
|
|
90
|
-
Settings.defaultZone = 'system';
|
|
91
|
-
Settings.now = () => originalNow;
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
const selectDay = (day: string, el: HTMLElement): void => {
|
|
95
|
-
if (!el.shadowRoot) {
|
|
96
|
-
throw new Error('Shadow root not found');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const allCells = el.shadowRoot.querySelectorAll('td[role="gridcell"]');
|
|
100
|
-
const dayCell = Array.from(allCells).filter((cell) => cell.textContent?.trim() === day)[0] as HTMLElement;
|
|
101
|
-
dayCell.click();
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
it('should emit date-selection event when selecting a date', async () => {
|
|
105
|
-
Settings.defaultZone = timezone;
|
|
106
|
-
const el = await fixture<Calendar>(html` <tt-calendar value="2025-01-09"></tt-calendar>`);
|
|
107
|
-
const listener = oneEvent(el, 'date-selection');
|
|
108
|
-
await elementUpdated(el);
|
|
109
|
-
selectDay('4', el);
|
|
110
|
-
|
|
111
|
-
await elementUpdated(el);
|
|
112
|
-
|
|
113
|
-
const { detail } = await listener;
|
|
114
|
-
const actual = detail as Date;
|
|
115
|
-
const expected = '2025-01-04';
|
|
116
|
-
expect(actual).to.equal(expected);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
['Australia/Brisbane', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Etc/UTC'].forEach((timezone) => {
|
|
121
|
-
describe('date range selection', () => {
|
|
122
|
-
it(`should emit date-range-selection event when selecting range in ${timezone} timezone`, async () => {
|
|
123
|
-
Settings.defaultZone = timezone;
|
|
124
|
-
Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();
|
|
125
|
-
const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);
|
|
126
|
-
const listener = oneEvent(el, 'date-range-selection');
|
|
127
|
-
|
|
128
|
-
el.toggleVisibility();
|
|
129
|
-
await elementUpdated(el);
|
|
130
|
-
|
|
131
|
-
const days = el.shadowRoot!.querySelectorAll('.day');
|
|
132
|
-
const firstDay = days[0] as HTMLElement;
|
|
133
|
-
const lastDay = days[5] as HTMLElement;
|
|
134
|
-
|
|
135
|
-
firstDay.click();
|
|
136
|
-
lastDay.click();
|
|
137
|
-
|
|
138
|
-
await elementUpdated(el);
|
|
139
|
-
|
|
140
|
-
const { detail } = await listener;
|
|
141
|
-
|
|
142
|
-
expect(detail).to.have.property('startDate');
|
|
143
|
-
expect(detail).to.have.property('endDate');
|
|
144
|
-
|
|
145
|
-
const { startDate, endDate } = detail;
|
|
146
|
-
const expectedStartDate = '2025-07-01';
|
|
147
|
-
const expectedEndDate = '2025-07-06';
|
|
148
|
-
await expect(startDate).to.equal(expectedStartDate);
|
|
149
|
-
await expect(endDate).to.equal(expectedEndDate);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('should disable dates before the start of the range when selecting', async () => {
|
|
153
|
-
Settings.defaultZone = timezone;
|
|
154
|
-
const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);
|
|
155
|
-
el.toggleVisibility();
|
|
156
|
-
await elementUpdated(el);
|
|
157
|
-
|
|
158
|
-
const days = el.shadowRoot!.querySelectorAll('.day');
|
|
159
|
-
(days[5] as HTMLElement).click();
|
|
160
|
-
await elementUpdated(el);
|
|
161
|
-
|
|
162
|
-
await expect(days[4].getAttribute('aria-disabled')).to.equal('true');
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('should disable dates before min-date', async () => {
|
|
166
|
-
Settings.defaultZone = timezone;
|
|
167
|
-
Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();
|
|
168
|
-
const el = await fixture<Calendar>(html` <tt-calendar min-date="2025-07-05"></tt-calendar>`);
|
|
169
|
-
el.toggleVisibility();
|
|
170
|
-
await elementUpdated(el);
|
|
171
|
-
|
|
172
|
-
const disabledDate = el.shadowRoot!.querySelector('[data-date="2025-07-04"]') as HTMLElement;
|
|
173
|
-
const enabledDate = el.shadowRoot!.querySelector('[data-date="2025-07-05"]') as HTMLElement;
|
|
174
|
-
|
|
175
|
-
await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');
|
|
176
|
-
await expect(enabledDate.getAttribute('aria-disabled')).to.equal('false');
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('should disable dates before max-date', async () => {
|
|
180
|
-
Settings.defaultZone = timezone;
|
|
181
|
-
Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();
|
|
182
|
-
const el = await fixture<Calendar>(html` <tt-calendar max-date="2025-07-05"></tt-calendar>`);
|
|
183
|
-
el.toggleVisibility();
|
|
184
|
-
await elementUpdated(el);
|
|
185
|
-
|
|
186
|
-
const disabledDate = el.shadowRoot!.querySelector('[data-date="2025-07-06"]') as HTMLElement;
|
|
187
|
-
const enabledDate = el.shadowRoot!.querySelector('[data-date="2025-07-05"]') as HTMLElement;
|
|
188
|
-
|
|
189
|
-
await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');
|
|
190
|
-
await expect(enabledDate.getAttribute('aria-disabled')).to.equal('false');
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('should disable dates after selected date + max days', async () => {
|
|
194
|
-
Settings.defaultZone = timezone;
|
|
195
|
-
Settings.now = () => DateTime.local(2025, 7, 1, 22, 0, 0).toMillis();
|
|
196
|
-
const el = await fixture<Calendar>(html` <tt-calendar range max-days="1"></tt-calendar>`);
|
|
197
|
-
el.toggleVisibility();
|
|
198
|
-
await elementUpdated(el);
|
|
199
|
-
|
|
200
|
-
const dateStart = el.shadowRoot!.querySelector('[data-date="2025-07-06"]') as HTMLElement;
|
|
201
|
-
dateStart.click();
|
|
202
|
-
await elementUpdated(el);
|
|
203
|
-
|
|
204
|
-
const disabledDate = el.shadowRoot!.querySelector('[data-date="2025-07-08"]') as HTMLElement;
|
|
205
|
-
|
|
206
|
-
await expect(disabledDate.getAttribute('aria-disabled')).to.equal('true');
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
describe('clear selection', () => {
|
|
212
|
-
it('should clear selection', async () => {
|
|
213
|
-
const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);
|
|
214
|
-
const listener = oneEvent(el, 'date-range-selection');
|
|
215
|
-
|
|
216
|
-
el.toggleVisibility();
|
|
217
|
-
await elementUpdated(el);
|
|
218
|
-
|
|
219
|
-
const clearButton = el.shadowRoot!.querySelector('button#clear-selection') as HTMLElement;
|
|
220
|
-
expect(clearButton).to.exist;
|
|
221
|
-
clearButton.click();
|
|
222
|
-
|
|
223
|
-
const { detail } = await listener;
|
|
224
|
-
expect(detail.startDate).to.be.undefined;
|
|
225
|
-
expect(detail.endDate).to.be.undefined;
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
describe('a11y', () => {
|
|
230
|
-
it('should have proper ARIA attributes', async () => {
|
|
231
|
-
const el = await fixture<Calendar>(html` <tt-calendar></tt-calendar>`);
|
|
232
|
-
el.toggleVisibility();
|
|
233
|
-
await elementUpdated(el);
|
|
234
|
-
|
|
235
|
-
const days = el.shadowRoot!.querySelectorAll('.day');
|
|
236
|
-
days.forEach((day) => {
|
|
237
|
-
expect(day.getAttribute('role')).to.equal('gridcell');
|
|
238
|
-
expect(day.getAttribute('aria-label')).to.exist;
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('should have proper ARIA selected states', async () => {
|
|
243
|
-
const el = await fixture<Calendar>(html` <tt-calendar range></tt-calendar>`);
|
|
244
|
-
el.toggleVisibility();
|
|
245
|
-
await elementUpdated(el);
|
|
246
|
-
|
|
247
|
-
const firstDay = el.shadowRoot!.querySelector('.day') as HTMLElement;
|
|
248
|
-
firstDay.click();
|
|
249
|
-
|
|
250
|
-
await elementUpdated(el);
|
|
251
|
-
|
|
252
|
-
await expect(firstDay?.getAttribute('aria-selected')).to.equal('true');
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
});
|
package/tsconfig.cjs.json
DELETED