@api-client/ui 0.5.6 → 0.5.8

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 (82) hide show
  1. package/.cursor/rules/html-and-css-best-practices.mdc +63 -0
  2. package/.cursor/rules/lit-best-practices.mdc +78 -0
  3. package/.github/instructions/html-and-css-best-practices.instructions.md +70 -0
  4. package/.github/instructions/lit-best-practices.instructions.md +86 -0
  5. package/build/src/elements/currency/currency-picker.d.ts +10 -0
  6. package/build/src/elements/currency/currency-picker.d.ts.map +1 -0
  7. package/build/src/elements/currency/currency-picker.js +27 -0
  8. package/build/src/elements/currency/currency-picker.js.map +1 -0
  9. package/build/src/elements/currency/internals/Picker.d.ts +311 -0
  10. package/build/src/elements/currency/internals/Picker.d.ts.map +1 -0
  11. package/build/src/elements/currency/internals/Picker.js +857 -0
  12. package/build/src/elements/currency/internals/Picker.js.map +1 -0
  13. package/build/src/elements/currency/internals/Picker.styles.d.ts +3 -0
  14. package/build/src/elements/currency/internals/Picker.styles.d.ts.map +1 -0
  15. package/build/src/elements/currency/internals/Picker.styles.js +58 -0
  16. package/build/src/elements/currency/internals/Picker.styles.js.map +1 -0
  17. package/build/src/elements/mention-textarea/internals/MentionTextArea.d.ts +216 -0
  18. package/build/src/elements/mention-textarea/internals/MentionTextArea.d.ts.map +1 -0
  19. package/build/src/elements/mention-textarea/internals/MentionTextArea.js +1037 -0
  20. package/build/src/elements/mention-textarea/internals/MentionTextArea.js.map +1 -0
  21. package/build/src/elements/mention-textarea/internals/MentionTextArea.styles.d.ts +3 -0
  22. package/build/src/elements/mention-textarea/internals/MentionTextArea.styles.d.ts.map +1 -0
  23. package/build/src/elements/mention-textarea/internals/MentionTextArea.styles.js +274 -0
  24. package/build/src/elements/mention-textarea/internals/MentionTextArea.styles.js.map +1 -0
  25. package/build/src/elements/mention-textarea/ui-mention-textarea.d.ts +13 -0
  26. package/build/src/elements/mention-textarea/ui-mention-textarea.d.ts.map +1 -0
  27. package/build/src/elements/mention-textarea/ui-mention-textarea.js +28 -0
  28. package/build/src/elements/mention-textarea/ui-mention-textarea.js.map +1 -0
  29. package/build/src/md/button/internals/base.d.ts +1 -0
  30. package/build/src/md/button/internals/base.d.ts.map +1 -1
  31. package/build/src/md/button/internals/base.js +7 -0
  32. package/build/src/md/button/internals/base.js.map +1 -1
  33. package/build/src/md/chip/internals/Chip.styles.d.ts.map +1 -1
  34. package/build/src/md/chip/internals/Chip.styles.js +2 -0
  35. package/build/src/md/chip/internals/Chip.styles.js.map +1 -1
  36. package/build/src/md/date-picker/internals/DatePicker.styles.d.ts.map +1 -1
  37. package/build/src/md/date-picker/internals/DatePicker.styles.js +73 -0
  38. package/build/src/md/date-picker/internals/DatePicker.styles.js.map +1 -1
  39. package/build/src/md/date-picker/internals/DatePickerCalendar.d.ts +164 -51
  40. package/build/src/md/date-picker/internals/DatePickerCalendar.d.ts.map +1 -1
  41. package/build/src/md/date-picker/internals/DatePickerCalendar.js +660 -368
  42. package/build/src/md/date-picker/internals/DatePickerCalendar.js.map +1 -1
  43. package/build/src/md/date-picker/ui-date-picker-input.d.ts +65 -13
  44. package/build/src/md/date-picker/ui-date-picker-input.d.ts.map +1 -1
  45. package/build/src/md/date-picker/ui-date-picker-input.js +143 -76
  46. package/build/src/md/date-picker/ui-date-picker-input.js.map +1 -1
  47. package/build/src/md/date-picker/ui-date-picker-modal-input.d.ts +76 -17
  48. package/build/src/md/date-picker/ui-date-picker-modal-input.d.ts.map +1 -1
  49. package/build/src/md/date-picker/ui-date-picker-modal-input.js +192 -127
  50. package/build/src/md/date-picker/ui-date-picker-modal-input.js.map +1 -1
  51. package/build/src/md/date-picker/ui-date-picker-modal.d.ts +63 -15
  52. package/build/src/md/date-picker/ui-date-picker-modal.d.ts.map +1 -1
  53. package/build/src/md/date-picker/ui-date-picker-modal.js +143 -64
  54. package/build/src/md/date-picker/ui-date-picker-modal.js.map +1 -1
  55. package/demo/elements/currency/index.html +91 -0
  56. package/demo/elements/currency/index.ts +272 -0
  57. package/demo/elements/index.html +6 -0
  58. package/demo/elements/mention-textarea/index.html +19 -0
  59. package/demo/elements/mention-textarea/index.ts +205 -0
  60. package/demo/md/date-picker/date-picker.ts +138 -103
  61. package/package.json +2 -2
  62. package/src/elements/currency/currency-picker.ts +14 -0
  63. package/src/elements/currency/internals/Picker.styles.ts +58 -0
  64. package/src/elements/currency/internals/Picker.ts +846 -0
  65. package/src/elements/mention-textarea/internals/MentionTextArea.styles.ts +274 -0
  66. package/src/elements/mention-textarea/internals/MentionTextArea.ts +1036 -0
  67. package/src/elements/mention-textarea/ui-mention-textarea.ts +18 -0
  68. package/src/md/button/internals/base.ts +7 -0
  69. package/src/md/chip/internals/Chip.styles.ts +2 -0
  70. package/src/md/date-picker/internals/DatePicker.styles.ts +73 -0
  71. package/src/md/date-picker/internals/DatePickerCalendar.ts +643 -309
  72. package/src/md/date-picker/ui-date-picker-input.ts +110 -49
  73. package/src/md/date-picker/ui-date-picker-modal-input.ts +168 -99
  74. package/src/md/date-picker/ui-date-picker-modal.ts +136 -53
  75. package/test/README.md +3 -2
  76. package/test/elements/currency/CurrencyPicker.accessibility.test.ts +328 -0
  77. package/test/elements/currency/CurrencyPicker.core.test.ts +318 -0
  78. package/test/elements/currency/CurrencyPicker.integration.test.ts +482 -0
  79. package/test/elements/currency/CurrencyPicker.test.ts +486 -0
  80. package/test/elements/mention-textarea/MentionTextArea.basic.test.ts +63 -0
  81. package/test/elements/mention-textarea/MentionTextArea.test.ts +321 -0
  82. package/tsconfig.json +1 -1
@@ -0,0 +1,318 @@
1
+ import { fixture, assert, html } from '@open-wc/testing'
2
+ import CurrencyPicker from '../../../src/elements/currency/internals/Picker.js'
3
+ import '../../../src/elements/currency/currency-picker.js'
4
+
5
+ describe('CurrencyPicker - Core Tests', () => {
6
+ async function basicFixture(): Promise<CurrencyPicker> {
7
+ return fixture(html`<currency-picker></currency-picker>`)
8
+ }
9
+
10
+ async function multiSelectFixture(): Promise<CurrencyPicker> {
11
+ return fixture(html`<currency-picker multi></currency-picker>`)
12
+ }
13
+
14
+ async function allowedCurrenciesFixture(): Promise<CurrencyPicker> {
15
+ return fixture(html`<currency-picker .allowedCurrencies="${['USD', 'EUR', 'GBP']}"></currency-picker>`)
16
+ }
17
+
18
+ async function requiredFixture(): Promise<CurrencyPicker> {
19
+ return fixture(html`<currency-picker required></currency-picker>`)
20
+ }
21
+
22
+ describe('Basic Functionality', () => {
23
+ let picker: CurrencyPicker
24
+
25
+ beforeEach(async () => {
26
+ picker = await basicFixture()
27
+ })
28
+
29
+ it('should create element', () => {
30
+ assert.instanceOf(picker, CurrencyPicker)
31
+ })
32
+
33
+ it('should have default properties', () => {
34
+ assert.deepEqual(picker.selected, [])
35
+ assert.deepEqual(picker.allowedCurrencies, [])
36
+ assert.equal(picker.label, 'Add Currency')
37
+ assert.isFalse(picker.multi)
38
+ assert.isFalse(picker.required)
39
+ assert.isFalse(picker.disabled)
40
+ assert.isTrue(picker.showErrors)
41
+ })
42
+
43
+ it('should render currency selector', () => {
44
+ const selector = picker.shadowRoot?.querySelector('md-outlined-select')
45
+ assert.exists(selector)
46
+ assert.equal(selector?.getAttribute('label'), 'Add Currency')
47
+ })
48
+
49
+ it('should populate currency options', async () => {
50
+ await picker.updateComplete
51
+ const options = picker.shadowRoot?.querySelectorAll('md-select-option')
52
+ assert.exists(options)
53
+ assert.isAtLeast(options?.length || 0, 25) // Should have popular currencies
54
+ })
55
+ })
56
+
57
+ describe('Currency Selection', () => {
58
+ let picker: CurrencyPicker
59
+
60
+ beforeEach(async () => {
61
+ picker = await basicFixture()
62
+ })
63
+
64
+ it('should select a currency', async () => {
65
+ picker.selected = ['USD']
66
+ await picker.updateComplete
67
+ assert.deepEqual(picker.selected, ['USD'])
68
+ })
69
+
70
+ it('should get selected currencies', async () => {
71
+ // Test single-select mode (default)
72
+ picker.selected = ['USD', 'EUR']
73
+ await picker.updateComplete
74
+
75
+ const currencies = picker.getSelectedCurrencies()
76
+ assert.equal(currencies.length, 1, 'Should only allow one selection in single-select mode')
77
+ assert.equal(currencies[0].code, 'USD')
78
+
79
+ // Test multi-select mode
80
+ picker.multi = true
81
+ picker.selected = ['USD', 'EUR']
82
+ await picker.updateComplete
83
+
84
+ const currenciesMulti = picker.getSelectedCurrencies()
85
+ assert.equal(currenciesMulti.length, 2)
86
+ assert.equal(currenciesMulti[0].code, 'USD')
87
+ assert.equal(currenciesMulti[1].code, 'EUR')
88
+ })
89
+
90
+ it('should clear selection', async () => {
91
+ picker.selected = ['USD', 'EUR']
92
+ await picker.updateComplete
93
+
94
+ picker.clearSelection()
95
+ await picker.updateComplete
96
+
97
+ assert.deepEqual(picker.selected, [])
98
+ })
99
+ })
100
+
101
+ describe('Multi-select Mode', () => {
102
+ let picker: CurrencyPicker
103
+
104
+ beforeEach(async () => {
105
+ picker = await multiSelectFixture()
106
+ })
107
+
108
+ it('should allow multiple selections', async () => {
109
+ picker.selected = ['USD', 'EUR', 'GBP']
110
+ await picker.updateComplete
111
+
112
+ assert.equal(picker.selected.length, 3)
113
+ assert.include(picker.selected, 'USD')
114
+ assert.include(picker.selected, 'EUR')
115
+ assert.include(picker.selected, 'GBP')
116
+ })
117
+
118
+ it('should render chips for selected currencies', async () => {
119
+ picker.selected = ['USD', 'EUR']
120
+ await picker.updateComplete
121
+
122
+ const chipSet = picker.shadowRoot?.querySelector('ui-chip-set')
123
+ const chips = picker.shadowRoot?.querySelectorAll('ui-chip')
124
+
125
+ assert.exists(chipSet)
126
+ assert.equal(chips?.length, 2)
127
+ })
128
+ })
129
+
130
+ describe('Allowed Currencies', () => {
131
+ let picker: CurrencyPicker
132
+
133
+ beforeEach(async () => {
134
+ picker = await allowedCurrenciesFixture()
135
+ })
136
+
137
+ it('should filter options based on allowed currencies', async () => {
138
+ await picker.updateComplete
139
+
140
+ const options = picker.shadowRoot?.querySelectorAll('md-select-option[value]')
141
+ const optionValues = Array.from(options || [])
142
+ .map((option) => option.getAttribute('value'))
143
+ .filter(Boolean)
144
+
145
+ // Should only have USD, EUR, GBP (plus empty option)
146
+ assert.isAtMost(optionValues.length, 3)
147
+ assert.include(optionValues, 'USD')
148
+ assert.include(optionValues, 'EUR')
149
+ assert.include(optionValues, 'GBP')
150
+ })
151
+ })
152
+
153
+ describe('Validation and Error Handling', () => {
154
+ let picker: CurrencyPicker
155
+
156
+ beforeEach(async () => {
157
+ picker = await requiredFixture()
158
+ })
159
+
160
+ it('should show error state in UI when showErrors is true', async () => {
161
+ picker.showErrors = true
162
+
163
+ // First set a value, then clear it to trigger validation
164
+ picker.selected = ['USD']
165
+ await picker.updateComplete
166
+
167
+ picker.selected = [] // This should trigger required validation error
168
+ await picker.updateComplete
169
+
170
+ const errorElement = picker.shadowRoot?.querySelector('.error')
171
+ const selectElement = picker.shadowRoot?.querySelector('md-outlined-select')
172
+ const isInvalid = !picker.validity.valid
173
+ const hasAriaInvalid = selectElement?.getAttribute('aria-invalid') === 'true'
174
+
175
+ assert.exists(errorElement, 'Error element should be displayed')
176
+ assert.isTrue(isInvalid, 'Component should be in invalid state')
177
+ assert.isTrue(hasAriaInvalid, 'Select element should have aria-invalid=true')
178
+ assert.isTrue(picker.matches(':invalid'), 'Has the :invalid pseudo-class')
179
+ })
180
+
181
+ it('should not show error UI when showErrors is false', async () => {
182
+ picker.showErrors = false
183
+ picker.selected = [] // Directly set to empty to trigger required validation error
184
+ await picker.updateComplete
185
+
186
+ const errorElement = picker.shadowRoot?.querySelector('.error')
187
+ assert.isNull(errorElement)
188
+ })
189
+
190
+ it('should validate invalid currency codes', async () => {
191
+ picker.selected = ['INVALID_CODE']
192
+ await picker.updateComplete
193
+
194
+ // Should filter out invalid codes
195
+ assert.notInclude(picker.selected, 'INVALID_CODE')
196
+ })
197
+
198
+ it('should prevent multiple selections in single-select mode', async () => {
199
+ picker.multi = false
200
+ picker.selected = ['USD', 'EUR'] // Multiple selections in single-select mode
201
+ await picker.updateComplete
202
+
203
+ // Should only keep one selection when multi=false
204
+ assert.equal(picker.selected.length, 1)
205
+ assert.equal(picker.selected[0], 'USD') // Should keep the first one
206
+ })
207
+ })
208
+
209
+ describe('Form Integration', () => {
210
+ it('should be form-associated', () => {
211
+ assert.isTrue(CurrencyPicker.formAssociated)
212
+ })
213
+
214
+ it('should handle form state restoration', async () => {
215
+ // Test single-select mode (default)
216
+ const pickerSingle = await basicFixture()
217
+ pickerSingle.formStateRestoreCallback('USD,EUR')
218
+ await pickerSingle.updateComplete
219
+
220
+ assert.deepEqual(pickerSingle.selected, ['USD'], 'Single-select should only restore first value')
221
+
222
+ // Test multi-select mode
223
+ const pickerMulti = await multiSelectFixture()
224
+ pickerMulti.formStateRestoreCallback('USD,EUR')
225
+ await pickerMulti.updateComplete
226
+
227
+ assert.deepEqual(pickerMulti.selected, ['USD', 'EUR'], 'Multi-select should restore all values')
228
+ })
229
+
230
+ it('should handle form reset', async () => {
231
+ const picker = await basicFixture()
232
+ picker.selected = ['USD', 'EUR']
233
+ await picker.updateComplete
234
+
235
+ picker.formResetCallback()
236
+ await picker.updateComplete
237
+
238
+ assert.deepEqual(picker.selected, [])
239
+ })
240
+ })
241
+
242
+ describe('Accessibility', () => {
243
+ let picker: CurrencyPicker
244
+
245
+ beforeEach(async () => {
246
+ picker = await basicFixture()
247
+ })
248
+
249
+ it('should have proper ARIA attributes', async () => {
250
+ await picker.updateComplete
251
+
252
+ const container = picker.shadowRoot?.querySelector('.currency-picker')
253
+ const select = picker.shadowRoot?.querySelector('md-outlined-select')
254
+
255
+ assert.equal(container?.getAttribute('role'), 'group')
256
+ assert.exists(container?.getAttribute('aria-label'))
257
+ assert.exists(select?.getAttribute('aria-invalid'))
258
+ })
259
+
260
+ it('should update ARIA label based on selection', async () => {
261
+ picker.selected = ['USD']
262
+ await picker.updateComplete
263
+
264
+ const container = picker.shadowRoot?.querySelector('.currency-picker')
265
+ const ariaLabel = container?.getAttribute('aria-label')
266
+
267
+ assert.include(ariaLabel || '', 'USD selected')
268
+ })
269
+
270
+ it('should have error announcements', async () => {
271
+ picker.showErrors = true
272
+ picker.required = true
273
+ picker.clearSelection()
274
+ await picker.updateComplete
275
+
276
+ const errorElement = picker.shadowRoot?.querySelector('.error')
277
+ assert.equal(errorElement?.getAttribute('role'), 'alert')
278
+ assert.equal(errorElement?.getAttribute('aria-live'), 'polite')
279
+ })
280
+ })
281
+
282
+ describe('Edge Cases', () => {
283
+ let picker: CurrencyPicker
284
+
285
+ beforeEach(async () => {
286
+ picker = await basicFixture()
287
+ })
288
+
289
+ it('should handle empty arrays gracefully', async () => {
290
+ picker.selected = []
291
+ picker.allowedCurrencies = []
292
+ await picker.updateComplete
293
+
294
+ assert.deepEqual(picker.selected, [])
295
+ assert.deepEqual(picker.getSelectedCurrencies(), [])
296
+ })
297
+
298
+ it('should handle disabled state', async () => {
299
+ picker.disabled = true
300
+ await picker.updateComplete
301
+
302
+ const select = picker.shadowRoot?.querySelector('md-outlined-select')
303
+ assert.isTrue(select?.hasAttribute('disabled'))
304
+ })
305
+
306
+ it('should handle disconnection/reconnection', async () => {
307
+ picker.selected = ['USD']
308
+ await picker.updateComplete
309
+
310
+ // Disconnect and reconnect
311
+ picker.remove()
312
+ document.body.appendChild(picker)
313
+ await picker.updateComplete
314
+
315
+ assert.deepEqual(picker.selected, ['USD'])
316
+ })
317
+ })
318
+ })