@oslokommune/punkt-elements 13.4.2 → 13.5.1
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/CHANGELOG.md +35 -0
- package/dist/calendar-32W9p9uc.cjs +115 -0
- package/dist/{calendar-DevQhOup.js → calendar-CJSxvwAq.js} +353 -340
- package/dist/{card-Dtw26f7i.js → card-BDz4RWxK.js} +1 -1
- package/dist/{card-BUITGoqX.cjs → card-DBlFf1ry.cjs} +1 -1
- package/dist/{datepicker-CYOn3tRm.js → datepicker-BJKJBoy_.js} +102 -59
- package/dist/datepicker-CmTrG5GE.cjs +164 -0
- package/dist/{heading-D6jXE_Mz.js → heading-Bdh9absf.js} +22 -22
- package/dist/heading-CNycsyMj.cjs +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/pkt-calendar.cjs +1 -1
- package/dist/pkt-calendar.js +1 -1
- package/dist/pkt-card.cjs +1 -1
- package/dist/pkt-card.js +1 -1
- package/dist/pkt-datepicker.cjs +1 -1
- package/dist/pkt-datepicker.js +1 -1
- package/dist/pkt-heading.cjs +1 -1
- package/dist/pkt-heading.js +1 -1
- package/dist/pkt-index.cjs +1 -1
- package/dist/pkt-index.js +5 -5
- package/package.json +3 -3
- package/src/components/calendar/calendar.accessibility.test.ts +111 -0
- package/src/components/calendar/calendar.constraints.test.ts +110 -0
- package/src/components/calendar/calendar.core.test.ts +367 -0
- package/src/components/calendar/calendar.interaction.test.ts +139 -0
- package/src/components/calendar/calendar.selection.test.ts +273 -0
- package/src/components/calendar/calendar.ts +74 -42
- package/src/components/card/card.test.ts +19 -5
- package/src/components/consent/consent.test.ts +436 -0
- package/src/components/datepicker/datepicker.accessibility.test.ts +193 -0
- package/src/components/datepicker/datepicker.core.test.ts +322 -0
- package/src/components/datepicker/datepicker.input.test.ts +268 -0
- package/src/components/datepicker/datepicker.selection.test.ts +286 -0
- package/src/components/datepicker/datepicker.ts +121 -19
- package/src/components/datepicker/datepicker.validation.test.ts +176 -0
- package/src/components/heading/heading.test.ts +458 -0
- package/src/components/heading/heading.ts +3 -0
- package/src/components/helptext/helptext.test.ts +474 -0
- package/dist/calendar-BZe2D4Sr.cjs +0 -108
- package/dist/datepicker-B9rhz_AF.cjs +0 -154
- package/dist/heading-BRE_iFtR.cjs +0 -1
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
2
|
+
import { fireEvent } from '@testing-library/dom'
|
|
3
|
+
|
|
4
|
+
import './datepicker'
|
|
5
|
+
import '../calendar/calendar'
|
|
6
|
+
import { PktDatepicker } from './datepicker'
|
|
7
|
+
|
|
8
|
+
const waitForCustomElements = async () => {
|
|
9
|
+
await customElements.whenDefined('pkt-datepicker')
|
|
10
|
+
await customElements.whenDefined('pkt-calendar')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Helper function to create datepicker markup
|
|
14
|
+
const createDatepicker = async (datepickerProps = '') => {
|
|
15
|
+
const container = document.createElement('div')
|
|
16
|
+
container.innerHTML = `
|
|
17
|
+
<pkt-datepicker ${datepickerProps}></pkt-datepicker>
|
|
18
|
+
`
|
|
19
|
+
document.body.appendChild(container)
|
|
20
|
+
await waitForCustomElements()
|
|
21
|
+
return container
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Cleanup after each test
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
document.body.innerHTML = ''
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
describe('PktDatepicker', () => {
|
|
30
|
+
describe('Multiple date selection', () => {
|
|
31
|
+
test('displays multiple selected dates as tags', async () => {
|
|
32
|
+
const multipleDates = '2024-06-15,2024-06-20,2024-06-25'
|
|
33
|
+
const container = await createDatepicker(`value="${multipleDates}" multiple`)
|
|
34
|
+
|
|
35
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
36
|
+
await datepicker.updateComplete
|
|
37
|
+
|
|
38
|
+
const tags = datepicker.querySelectorAll('pkt-tag')
|
|
39
|
+
expect(tags.length).toBe(3)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('allows adding dates through calendar in multiple mode', async () => {
|
|
43
|
+
const container = await createDatepicker('multiple')
|
|
44
|
+
|
|
45
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
46
|
+
await datepicker.updateComplete
|
|
47
|
+
|
|
48
|
+
// Open calendar
|
|
49
|
+
const calendarButton = datepicker.querySelector('button[type="button"]')
|
|
50
|
+
fireEvent.click(calendarButton!)
|
|
51
|
+
await datepicker.updateComplete
|
|
52
|
+
|
|
53
|
+
// Select a date
|
|
54
|
+
const availableDate = datepicker.querySelector('[data-date]:not([data-disabled="disabled"])')
|
|
55
|
+
if (availableDate) {
|
|
56
|
+
fireEvent.click(availableDate)
|
|
57
|
+
await datepicker.updateComplete
|
|
58
|
+
|
|
59
|
+
// Should add tag
|
|
60
|
+
const tags = datepicker.querySelectorAll('pkt-tag')
|
|
61
|
+
expect(tags.length).toBe(1)
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('removes dates when clicking tag close button', async () => {
|
|
66
|
+
const multipleDates = '2024-06-15,2024-06-20'
|
|
67
|
+
const container = await createDatepicker(`value="${multipleDates}" multiple`)
|
|
68
|
+
|
|
69
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
70
|
+
await datepicker.updateComplete
|
|
71
|
+
|
|
72
|
+
const closeButtons = datepicker.querySelectorAll('pkt-tag .pkt-tag__close-btn')
|
|
73
|
+
expect(closeButtons.length).toBe(2)
|
|
74
|
+
|
|
75
|
+
// Click first close button
|
|
76
|
+
fireEvent.click(closeButtons[0])
|
|
77
|
+
await datepicker.updateComplete
|
|
78
|
+
|
|
79
|
+
const remainingTags = datepicker.querySelectorAll('pkt-tag')
|
|
80
|
+
expect(remainingTags.length).toBe(1)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('respects maxlength in multiple mode', async () => {
|
|
84
|
+
const container = await createDatepicker('multiple maxlength="2"')
|
|
85
|
+
|
|
86
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
87
|
+
await datepicker.updateComplete
|
|
88
|
+
|
|
89
|
+
// Open calendar and try to select more than maxlength dates
|
|
90
|
+
const calendarButton = datepicker.querySelector('button[type="button"]')
|
|
91
|
+
fireEvent.click(calendarButton!)
|
|
92
|
+
await datepicker.updateComplete
|
|
93
|
+
|
|
94
|
+
const availableDates = datepicker.querySelectorAll(
|
|
95
|
+
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
// Select 3 dates
|
|
99
|
+
fireEvent.click(availableDates[0])
|
|
100
|
+
await datepicker.updateComplete
|
|
101
|
+
fireEvent.click(availableDates[1])
|
|
102
|
+
await datepicker.updateComplete
|
|
103
|
+
fireEvent.click(availableDates[2])
|
|
104
|
+
await datepicker.updateComplete
|
|
105
|
+
|
|
106
|
+
// Should only have maxlength tags
|
|
107
|
+
const tags = datepicker.querySelectorAll('pkt-tag')
|
|
108
|
+
expect(tags.length).toBeLessThanOrEqual(2)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('sorts multiple dates chronologically', async () => {
|
|
112
|
+
const unsortedDates = '2024-06-25,2024-06-15,2024-06-20'
|
|
113
|
+
const container = await createDatepicker(`value="${unsortedDates}" multiple`)
|
|
114
|
+
|
|
115
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
116
|
+
await datepicker.updateComplete
|
|
117
|
+
|
|
118
|
+
const tags = datepicker.querySelectorAll('pkt-tag')
|
|
119
|
+
const tagTexts = Array.from(tags).map((tag) => tag.textContent?.trim())
|
|
120
|
+
|
|
121
|
+
// Should be sorted chronologically
|
|
122
|
+
expect(tagTexts[0]).toContain('15')
|
|
123
|
+
expect(tagTexts[1]).toContain('20')
|
|
124
|
+
expect(tagTexts[2]).toContain('25')
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
describe('Range selection', () => {
|
|
129
|
+
test('displays range labels when showRangeLabels is true', async () => {
|
|
130
|
+
const rangeValue = '2024-06-15,2024-06-20'
|
|
131
|
+
const container = await createDatepicker(`value="${rangeValue}" range showRangeLabels`)
|
|
132
|
+
|
|
133
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
134
|
+
await datepicker.updateComplete
|
|
135
|
+
|
|
136
|
+
expect(datepicker.showRangeLabels).toBe(true)
|
|
137
|
+
|
|
138
|
+
const rangeLabels = datepicker.querySelectorAll('.pkt-input-prefix')
|
|
139
|
+
expect(rangeLabels.length).toBeGreaterThan(0)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test('populates both input fields when initialized with range value', async () => {
|
|
143
|
+
const rangeValue = '2024-06-15,2024-06-20'
|
|
144
|
+
const container = await createDatepicker(`value="${rangeValue}" range`)
|
|
145
|
+
|
|
146
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
147
|
+
await datepicker.updateComplete
|
|
148
|
+
|
|
149
|
+
const inputs = datepicker.querySelectorAll('input')
|
|
150
|
+
expect(inputs.length).toBe(2)
|
|
151
|
+
|
|
152
|
+
// Check that both input fields are populated
|
|
153
|
+
expect(inputs[0].value).toBe('2024-06-15')
|
|
154
|
+
expect(inputs[1].value).toBe('2024-06-20')
|
|
155
|
+
|
|
156
|
+
// Check internal state
|
|
157
|
+
expect(datepicker._value).toEqual(['2024-06-15', '2024-06-20'])
|
|
158
|
+
expect(datepicker.value).toBe('2024-06-15,2024-06-20')
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('dispatches value-change event with array for range and multiple datepickers', async () => {
|
|
162
|
+
// Test range datepicker
|
|
163
|
+
const rangeContainer = await createDatepicker('range')
|
|
164
|
+
const rangeDatepicker = rangeContainer.querySelector('pkt-datepicker') as PktDatepicker
|
|
165
|
+
await rangeDatepicker.updateComplete
|
|
166
|
+
|
|
167
|
+
let valueChangeEvent: CustomEvent | null = null
|
|
168
|
+
rangeDatepicker.addEventListener('value-change', (e: Event) => {
|
|
169
|
+
valueChangeEvent = e as CustomEvent
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
// Set a range value programmatically
|
|
173
|
+
rangeDatepicker.value = '2024-06-15,2024-06-20'
|
|
174
|
+
await rangeDatepicker.updateComplete
|
|
175
|
+
|
|
176
|
+
expect(valueChangeEvent).toBeTruthy()
|
|
177
|
+
expect(valueChangeEvent!.detail).toEqual(['2024-06-15', '2024-06-20'])
|
|
178
|
+
|
|
179
|
+
// Test multiple datepicker
|
|
180
|
+
const multipleContainer = await createDatepicker('multiple')
|
|
181
|
+
const multipleDatepicker = multipleContainer.querySelector('pkt-datepicker') as PktDatepicker
|
|
182
|
+
await multipleDatepicker.updateComplete
|
|
183
|
+
|
|
184
|
+
valueChangeEvent = null
|
|
185
|
+
multipleDatepicker.addEventListener('value-change', (e: Event) => {
|
|
186
|
+
valueChangeEvent = e as CustomEvent
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
// Set multiple values programmatically
|
|
190
|
+
multipleDatepicker.value = '2024-06-15,2024-06-20,2024-06-25'
|
|
191
|
+
await multipleDatepicker.updateComplete
|
|
192
|
+
|
|
193
|
+
expect(valueChangeEvent).toBeTruthy()
|
|
194
|
+
expect(valueChangeEvent!.detail).toEqual(['2024-06-15', '2024-06-20', '2024-06-25'])
|
|
195
|
+
|
|
196
|
+
// Test single datepicker
|
|
197
|
+
const singleContainer = await createDatepicker('')
|
|
198
|
+
const singleDatepicker = singleContainer.querySelector('pkt-datepicker') as PktDatepicker
|
|
199
|
+
await singleDatepicker.updateComplete
|
|
200
|
+
|
|
201
|
+
valueChangeEvent = null
|
|
202
|
+
singleDatepicker.addEventListener('value-change', (e: Event) => {
|
|
203
|
+
valueChangeEvent = e as CustomEvent
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
// Set single value programmatically
|
|
207
|
+
singleDatepicker.value = '2024-06-15'
|
|
208
|
+
await singleDatepicker.updateComplete
|
|
209
|
+
|
|
210
|
+
expect(valueChangeEvent).toBeTruthy()
|
|
211
|
+
expect(valueChangeEvent!.detail).toBe('2024-06-15')
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
test('handles range selection through calendar', async () => {
|
|
215
|
+
const container = await createDatepicker('range')
|
|
216
|
+
|
|
217
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
218
|
+
await datepicker.updateComplete
|
|
219
|
+
|
|
220
|
+
// Open calendar
|
|
221
|
+
const calendarButton = datepicker.querySelector('button[type="button"]')
|
|
222
|
+
fireEvent.click(calendarButton!)
|
|
223
|
+
await datepicker.updateComplete
|
|
224
|
+
|
|
225
|
+
const availableDates = datepicker.querySelectorAll(
|
|
226
|
+
'[data-date]:not([data-disabled="disabled"])',
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
// Select start date
|
|
230
|
+
if (availableDates.length > 5) {
|
|
231
|
+
fireEvent.click(availableDates[5])
|
|
232
|
+
await datepicker.updateComplete
|
|
233
|
+
|
|
234
|
+
// Select end date
|
|
235
|
+
if (availableDates.length > 10) {
|
|
236
|
+
fireEvent.click(availableDates[10])
|
|
237
|
+
await datepicker.updateComplete
|
|
238
|
+
|
|
239
|
+
// Should have range value
|
|
240
|
+
expect(datepicker.value).toContain(',')
|
|
241
|
+
const values = (datepicker.value as string).split(',')
|
|
242
|
+
expect(values.length).toBe(2)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
test('validates range order', async () => {
|
|
248
|
+
const invalidRange = '2024-06-20,2024-06-15' // End before start
|
|
249
|
+
const container = await createDatepicker(`value="${invalidRange}" range`)
|
|
250
|
+
|
|
251
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
252
|
+
await datepicker.updateComplete
|
|
253
|
+
|
|
254
|
+
// Should handle invalid range gracefully
|
|
255
|
+
expect(datepicker).toBeInTheDocument()
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
test('shows range preview on hover', async () => {
|
|
259
|
+
const container = await createDatepicker('range')
|
|
260
|
+
|
|
261
|
+
const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
|
|
262
|
+
await datepicker.updateComplete
|
|
263
|
+
|
|
264
|
+
// Open calendar
|
|
265
|
+
const calendarButton = datepicker.querySelector('button[type="button"]')
|
|
266
|
+
fireEvent.click(calendarButton!)
|
|
267
|
+
await datepicker.updateComplete
|
|
268
|
+
|
|
269
|
+
const availableDates = datepicker.querySelectorAll(
|
|
270
|
+
'.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
// Select start date
|
|
274
|
+
fireEvent.click(availableDates[5])
|
|
275
|
+
await datepicker.updateComplete
|
|
276
|
+
|
|
277
|
+
// Hover over potential end date
|
|
278
|
+
fireEvent.mouseOver(availableDates[10])
|
|
279
|
+
await datepicker.updateComplete
|
|
280
|
+
|
|
281
|
+
// Should show hover preview
|
|
282
|
+
const hoverRanges = datepicker.querySelectorAll('.pkt-calendar__date--in-range-hover')
|
|
283
|
+
expect(hoverRanges.length).toBeGreaterThan(0)
|
|
284
|
+
})
|
|
285
|
+
})
|
|
286
|
+
})
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { classMap } from 'lit/directives/class-map.js'
|
|
2
2
|
import { ifDefined } from 'lit/directives/if-defined.js'
|
|
3
3
|
import { customElement, property, state } from 'lit/decorators.js'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
formatISODate,
|
|
6
|
+
fromISOToDate,
|
|
7
|
+
fromISOtoLocal,
|
|
8
|
+
newDate,
|
|
9
|
+
parseISODateString,
|
|
10
|
+
} from '@/utils/dateutils'
|
|
5
11
|
import { html, nothing, PropertyValues } from 'lit'
|
|
6
12
|
import { PktCalendar } from '@/components/calendar/calendar'
|
|
7
13
|
import { PktInputElement } from '@/base-elements/input-element'
|
|
@@ -21,15 +27,22 @@ export class PktDatepicker extends PktInputElement {
|
|
|
21
27
|
/**
|
|
22
28
|
* Element attributes and properties
|
|
23
29
|
*/
|
|
30
|
+
private _valueProperty: string = ''
|
|
31
|
+
|
|
24
32
|
@property({ type: String, reflect: true })
|
|
25
|
-
value: string
|
|
33
|
+
get value(): string {
|
|
34
|
+
return this._valueProperty
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
set value(newValue: string | string[]) {
|
|
38
|
+
const oldValue = this._valueProperty
|
|
39
|
+
this._valueProperty = Array.isArray(newValue) ? newValue.join(',') : newValue || ''
|
|
40
|
+
this.valueChanged(this._valueProperty, oldValue)
|
|
41
|
+
this.requestUpdate('value', oldValue)
|
|
42
|
+
}
|
|
26
43
|
|
|
27
44
|
@property({ type: Array })
|
|
28
|
-
_value: string[] =
|
|
29
|
-
? !Array.isArray(this.value)
|
|
30
|
-
? this.value.split(',')
|
|
31
|
-
: this.value
|
|
32
|
-
: []
|
|
45
|
+
_value: string[] = []
|
|
33
46
|
|
|
34
47
|
@property({ type: String, reflect: true })
|
|
35
48
|
label: string = 'Datovelger'
|
|
@@ -112,8 +125,17 @@ export class PktDatepicker extends PktInputElement {
|
|
|
112
125
|
}
|
|
113
126
|
})
|
|
114
127
|
|
|
115
|
-
|
|
116
|
-
|
|
128
|
+
document &&
|
|
129
|
+
document.body.addEventListener('keydown', (e: KeyboardEvent) => {
|
|
130
|
+
if (e.key === 'Escape' && this.calendarOpen) {
|
|
131
|
+
this.hideCalendar()
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
if (this.value) {
|
|
136
|
+
this._value = Array.isArray(this.value)
|
|
137
|
+
? this.value.filter(Boolean)
|
|
138
|
+
: this.value.split(',').filter(Boolean)
|
|
117
139
|
}
|
|
118
140
|
this.min = this.min || specs.props.min.default
|
|
119
141
|
this.max = this.max || specs.props.max.default
|
|
@@ -151,10 +173,55 @@ export class PktDatepicker extends PktInputElement {
|
|
|
151
173
|
})
|
|
152
174
|
}
|
|
153
175
|
|
|
176
|
+
onInput(): void {
|
|
177
|
+
// Trigger input event for form validation
|
|
178
|
+
this.dispatchEvent(new Event('input', { bubbles: true }))
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
valueChanged(newValue: string | null, oldValue: string | null): void {
|
|
182
|
+
if (newValue !== oldValue) {
|
|
183
|
+
let validatedValue: string[] = []
|
|
184
|
+
|
|
185
|
+
if (newValue) {
|
|
186
|
+
// Handle case where newValue might be a string or need conversion
|
|
187
|
+
if (typeof newValue === 'string') {
|
|
188
|
+
validatedValue = newValue.split(',').filter(Boolean)
|
|
189
|
+
} else {
|
|
190
|
+
// If not a string, convert to string first
|
|
191
|
+
validatedValue = String(newValue).split(',').filter(Boolean)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Validate dates against min/max boundaries
|
|
196
|
+
if (this.min || this.max) {
|
|
197
|
+
const minDate = this.min ? new Date(this.min) : null
|
|
198
|
+
const maxDate = this.max ? new Date(this.max) : null
|
|
199
|
+
|
|
200
|
+
validatedValue = validatedValue.filter((dateStr) => {
|
|
201
|
+
const date = new Date(dateStr)
|
|
202
|
+
if (isNaN(date.getTime())) return false
|
|
203
|
+
if (minDate && date < minDate) return false
|
|
204
|
+
if (maxDate && date > maxDate) return false
|
|
205
|
+
return true
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
this._value = validatedValue
|
|
210
|
+
|
|
211
|
+
// Update the public value property to reflect validated value
|
|
212
|
+
const validatedValueString = validatedValue.join(',')
|
|
213
|
+
if (this._valueProperty !== validatedValueString) {
|
|
214
|
+
this._valueProperty = validatedValueString
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Call base class valueChanged to handle events properly
|
|
218
|
+
super.valueChanged(validatedValueString, oldValue)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
154
222
|
attributeChangedCallback(name: string, _old: string | null, value: string | null): void {
|
|
155
|
-
if (name === 'value') {
|
|
156
|
-
|
|
157
|
-
if (this.value !== _old) this.valueChanged(value, _old)
|
|
223
|
+
if (name === 'value' && this.value !== _old) {
|
|
224
|
+
this.valueChanged(value, _old)
|
|
158
225
|
}
|
|
159
226
|
|
|
160
227
|
if (name === 'excludedates' && typeof this.excludedates === 'string') {
|
|
@@ -168,6 +235,12 @@ export class PktDatepicker extends PktInputElement {
|
|
|
168
235
|
}
|
|
169
236
|
|
|
170
237
|
updated(changedProperties: PropertyValues): void {
|
|
238
|
+
if (changedProperties.has('value')) {
|
|
239
|
+
const newValue = Array.isArray(this.value) ? this.value.join(',') : this.value
|
|
240
|
+
const oldValue = changedProperties.get('value')
|
|
241
|
+
const oldValueStr = Array.isArray(oldValue) ? oldValue.join(',') : oldValue
|
|
242
|
+
this.valueChanged(newValue, oldValueStr)
|
|
243
|
+
}
|
|
171
244
|
if (changedProperties.has('multiple')) {
|
|
172
245
|
// If multiple is now true, ensure _value is an array of non-empty strings
|
|
173
246
|
if (this.multiple && !Array.isArray(this._value)) {
|
|
@@ -180,8 +253,8 @@ export class PktDatepicker extends PktInputElement {
|
|
|
180
253
|
} else if (!this.multiple && Array.isArray(this._value)) {
|
|
181
254
|
this._value = this._value.filter(Boolean)
|
|
182
255
|
}
|
|
183
|
-
// If multiple is now false, ensure _value is a single value
|
|
184
|
-
if (!this.multiple && Array.isArray(this._value)) {
|
|
256
|
+
// If multiple is now false, ensure _value is a single value (but not for range datepickers)
|
|
257
|
+
if (!this.multiple && !this.range && Array.isArray(this._value)) {
|
|
185
258
|
this._value = [this._value[0] ?? '']
|
|
186
259
|
}
|
|
187
260
|
}
|
|
@@ -212,6 +285,9 @@ export class PktDatepicker extends PktInputElement {
|
|
|
212
285
|
.value=${this._value[0] ?? ''}
|
|
213
286
|
min=${ifDefined(this.min)}
|
|
214
287
|
max=${ifDefined(this.max)}
|
|
288
|
+
placeholder=${ifDefined(this.placeholder)}
|
|
289
|
+
?readonly=${this.readonly}
|
|
290
|
+
aria-describedby="${this.id}-helptext"
|
|
215
291
|
@click=${(e: MouseEvent) => {
|
|
216
292
|
e.preventDefault()
|
|
217
293
|
this.showCalendar()
|
|
@@ -276,6 +352,8 @@ export class PktDatepicker extends PktInputElement {
|
|
|
276
352
|
.value=${this._value[0] ?? ''}
|
|
277
353
|
min=${ifDefined(this.min)}
|
|
278
354
|
max=${ifDefined(this.max)}
|
|
355
|
+
placeholder=${ifDefined(this.placeholder)}
|
|
356
|
+
?readonly=${this.readonly}
|
|
279
357
|
?disabled=${this.disabled}
|
|
280
358
|
@click=${(e: MouseEvent) => {
|
|
281
359
|
e.preventDefault()
|
|
@@ -339,6 +417,8 @@ export class PktDatepicker extends PktInputElement {
|
|
|
339
417
|
.value=${this._value[1] ?? ''}
|
|
340
418
|
min=${ifDefined(this.min)}
|
|
341
419
|
max=${ifDefined(this.max)}
|
|
420
|
+
placeholder=${ifDefined(this.placeholder)}
|
|
421
|
+
?readonly=${this.readonly}
|
|
342
422
|
?disabled=${this.disabled}
|
|
343
423
|
@click=${(e: MouseEvent) => {
|
|
344
424
|
e.preventDefault()
|
|
@@ -409,7 +489,6 @@ export class PktDatepicker extends PktInputElement {
|
|
|
409
489
|
}
|
|
410
490
|
|
|
411
491
|
renderMultipleInput() {
|
|
412
|
-
console.log('range', this.range, 'multiple', this.multiple)
|
|
413
492
|
return html`
|
|
414
493
|
<input
|
|
415
494
|
class=${classMap(this.inputClasses)}
|
|
@@ -417,6 +496,8 @@ export class PktDatepicker extends PktInputElement {
|
|
|
417
496
|
id="${this.id}-input"
|
|
418
497
|
min=${ifDefined(this.min)}
|
|
419
498
|
max=${ifDefined(this.max)}
|
|
499
|
+
placeholder=${ifDefined(this.placeholder)}
|
|
500
|
+
?readonly=${this.readonly}
|
|
420
501
|
?disabled=${this.disabled || (this.maxlength && this._value.length >= this.maxlength)}
|
|
421
502
|
@click=${(e: MouseEvent) => {
|
|
422
503
|
e.preventDefault()
|
|
@@ -470,7 +551,7 @@ export class PktDatepicker extends PktInputElement {
|
|
|
470
551
|
<div class="pkt-datepicker__tags" aria-live="polite">
|
|
471
552
|
${!!this._value[0]
|
|
472
553
|
? repeat(
|
|
473
|
-
(this._value ?? []).filter(Boolean),
|
|
554
|
+
(this._value ?? []).filter(Boolean).sort(),
|
|
474
555
|
(date) => date,
|
|
475
556
|
(date) => html`
|
|
476
557
|
<pkt-tag
|
|
@@ -513,16 +594,26 @@ export class PktDatepicker extends PktInputElement {
|
|
|
513
594
|
? this.excludedates
|
|
514
595
|
: (this.excludedates as string).split(',')}
|
|
515
596
|
.excludeweekdays=${this.excludeweekdays}
|
|
516
|
-
.currentmonth=${this.currentmonth ?
|
|
597
|
+
.currentmonth=${this.currentmonth ? parseISODateString(this.currentmonth) : null}
|
|
517
598
|
@date-selected=${(e: CustomEvent) => {
|
|
518
|
-
this.value =
|
|
599
|
+
this.value =
|
|
600
|
+
!this.multiple && !this.range
|
|
601
|
+
? e.detail[0]
|
|
602
|
+
: Array.isArray(e.detail)
|
|
603
|
+
? e.detail.join(',')
|
|
604
|
+
: e.detail
|
|
519
605
|
this._value = e.detail
|
|
520
606
|
if (this.inputRef.value) {
|
|
521
607
|
if (this.range && this.inputRefTo.value) {
|
|
522
608
|
this.inputRef.value.value = this._value[0] ?? ''
|
|
523
609
|
this.inputRefTo.value.value = this._value[1] ?? ''
|
|
610
|
+
// Update validity state after programmatic value change
|
|
611
|
+
this.manageValidity(this.inputRef.value)
|
|
612
|
+
this.manageValidity(this.inputRefTo.value)
|
|
524
613
|
} else if (!this.multiple) {
|
|
525
614
|
this.inputRef.value.value = this._value.length ? this._value[0] : ''
|
|
615
|
+
// Update validity state after programmatic value change
|
|
616
|
+
this.manageValidity(this.inputRef.value)
|
|
526
617
|
}
|
|
527
618
|
}
|
|
528
619
|
}}
|
|
@@ -536,7 +627,6 @@ export class PktDatepicker extends PktInputElement {
|
|
|
536
627
|
}
|
|
537
628
|
|
|
538
629
|
render() {
|
|
539
|
-
console.log('multiple', this.multiple, 'value', this.value, '_value', this._value)
|
|
540
630
|
this.inputClasses = {
|
|
541
631
|
'pkt-input': true,
|
|
542
632
|
'pkt-datepicker__input': true,
|
|
@@ -551,6 +641,7 @@ export class PktDatepicker extends PktInputElement {
|
|
|
551
641
|
'pkt-btn': true,
|
|
552
642
|
'pkt-btn--icon-only': true,
|
|
553
643
|
'pkt-btn--tertiary': true,
|
|
644
|
+
'pkt-datepicker__calendar-button': true,
|
|
554
645
|
}
|
|
555
646
|
|
|
556
647
|
return html`
|
|
@@ -595,6 +686,12 @@ export class PktDatepicker extends PktInputElement {
|
|
|
595
686
|
class="${classMap(this.buttonClasses)}"
|
|
596
687
|
type="button"
|
|
597
688
|
@click=${this.toggleCalendar}
|
|
689
|
+
@keydown=${(e: KeyboardEvent) => {
|
|
690
|
+
if (e.key === 'Enter' || e.key === ' ' || e.key === 'Space') {
|
|
691
|
+
e.preventDefault()
|
|
692
|
+
this.toggleCalendar(e)
|
|
693
|
+
}
|
|
694
|
+
}}
|
|
598
695
|
?disabled=${this.disabled}
|
|
599
696
|
${ref(this.btnRef)}
|
|
600
697
|
>
|
|
@@ -677,4 +774,9 @@ export class PktDatepicker extends PktInputElement {
|
|
|
677
774
|
e.preventDefault()
|
|
678
775
|
this.calendarOpen ? this.hideCalendar() : this.showCalendar()
|
|
679
776
|
}
|
|
777
|
+
|
|
778
|
+
public clearInputValue() {
|
|
779
|
+
this._value = []
|
|
780
|
+
this.value = ''
|
|
781
|
+
}
|
|
680
782
|
}
|