@noctuatech/uswds 0.0.36 → 0.1.2

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 (143) hide show
  1. package/assets/flags/alabama.svg +5 -0
  2. package/assets/flags/alaska.svg +14 -0
  3. package/assets/flags/arizona.svg +7 -0
  4. package/assets/flags/arkansas.svg +15 -0
  5. package/assets/flags/california.svg +8 -0
  6. package/assets/flags/colorado.svg +8 -0
  7. package/assets/flags/connecticut.svg +5 -0
  8. package/assets/flags/delaware.svg +7 -0
  9. package/assets/flags/florida.svg +5 -0
  10. package/assets/flags/georgia.svg +5 -0
  11. package/assets/flags/hawaii.svg +19 -0
  12. package/assets/flags/idaho.svg +5 -0
  13. package/assets/flags/illinois.svg +5 -0
  14. package/assets/flags/indiana.svg +15 -0
  15. package/assets/flags/iowa.svg +13 -0
  16. package/assets/flags/kansas.svg +5 -0
  17. package/assets/flags/kentucky.svg +16 -0
  18. package/assets/flags/louisiana.svg +14 -0
  19. package/assets/flags/maine.svg +12 -0
  20. package/assets/flags/maryland.svg +14 -0
  21. package/assets/flags/massachusetts.svg +15 -0
  22. package/assets/flags/michigan.svg +5 -0
  23. package/assets/flags/minnesota.svg +15 -0
  24. package/assets/flags/mississippi.svg +10 -0
  25. package/assets/flags/missouri.svg +16 -0
  26. package/assets/flags/montana.svg +11 -0
  27. package/assets/flags/nebraska.svg +13 -0
  28. package/assets/flags/nevada.svg +14 -0
  29. package/assets/flags/new_hampshire.svg +13 -0
  30. package/assets/flags/new_jersey.svg +13 -0
  31. package/assets/flags/new_mexico.svg +7 -0
  32. package/assets/flags/new_york.svg +13 -0
  33. package/assets/flags/north_carolina.svg +5 -0
  34. package/assets/flags/north_dakota.svg +13 -0
  35. package/assets/flags/ohio.svg +16 -0
  36. package/assets/flags/oklahoma.svg +12 -0
  37. package/assets/flags/oregon.svg +13 -0
  38. package/assets/flags/pennsylvania.svg +15 -0
  39. package/assets/flags/rhode_island.svg +13 -0
  40. package/assets/flags/south_carolina.svg +11 -0
  41. package/assets/flags/south_dakota.svg +15 -0
  42. package/assets/flags/tennessee.svg +13 -0
  43. package/assets/flags/texas.svg +8 -0
  44. package/assets/flags/utah.svg +9 -0
  45. package/assets/flags/vermont.svg +13 -0
  46. package/assets/flags/virginia.svg +5 -0
  47. package/assets/flags/washington.svg +5 -0
  48. package/assets/flags/west_virginia.svg +24 -0
  49. package/assets/flags/wisconsin.svg +5 -0
  50. package/assets/flags/wyoming.svg +5 -0
  51. package/package.json +13 -5
  52. package/src/lib/accordion/accordion.test.ts +12 -10
  53. package/src/lib/button/button.stories.ts +1 -1
  54. package/src/lib/card/card.stories.ts +0 -1
  55. package/src/lib/checkbox/checkbox.element.ts +1 -17
  56. package/src/lib/checkbox/checkbox.stories.ts +0 -27
  57. package/src/lib/combo-box/combo-box-option/combo-box-option.element.ts +68 -0
  58. package/src/lib/combo-box/combo-box.element.ts +222 -0
  59. package/src/lib/combo-box/combo-box.stories.ts +236 -0
  60. package/src/lib/combo-box/combo-box.test.ts +150 -0
  61. package/src/lib/combo-box/context.ts +10 -0
  62. package/src/lib/define.ts +3 -0
  63. package/src/lib/input/input.element.ts +4 -0
  64. package/src/lib/input/input.test.ts +2 -4
  65. package/src/lib/radio/radio-option/radio-option.element.ts +2 -6
  66. package/src/lib/radio/radio.element.ts +1 -1
  67. package/src/lib/radio/radio.stories.ts +0 -1
  68. package/src/lib/range-slider/range-slider.element.ts +111 -0
  69. package/src/lib/range-slider/range-slider.stories.ts +24 -0
  70. package/src/lib/range-slider/range-slider.test.ts +52 -0
  71. package/src/lib/select/select.stories.ts +1 -1
  72. package/src/lib/select/select.test.ts +2 -4
  73. package/src/lib/side-nav/side-nav.stories.ts +1 -1
  74. package/src/lib/summary-box/summary-box.stories.ts +1 -1
  75. package/src/lib/textarea/textarea.test.ts +2 -4
  76. package/src/lib.ts +3 -0
  77. package/target/lib/accordion/accordion.test.js +12 -10
  78. package/target/lib/accordion/accordion.test.js.map +1 -1
  79. package/target/lib/button/button.stories.d.ts +1 -1
  80. package/target/lib/button/button.stories.js +1 -1
  81. package/target/lib/button/button.stories.js.map +1 -1
  82. package/target/lib/card/card.stories.js.map +1 -1
  83. package/target/lib/checkbox/checkbox.element.d.ts +0 -1
  84. package/target/lib/checkbox/checkbox.element.js +1 -15
  85. package/target/lib/checkbox/checkbox.element.js.map +1 -1
  86. package/target/lib/checkbox/checkbox.stories.d.ts +0 -1
  87. package/target/lib/checkbox/checkbox.stories.js +0 -24
  88. package/target/lib/checkbox/checkbox.stories.js.map +1 -1
  89. package/target/lib/combo-box/combo-box-option/combo-box-option.element.d.ts +12 -0
  90. package/target/lib/combo-box/combo-box-option/combo-box-option.element.js +72 -0
  91. package/target/lib/combo-box/combo-box-option/combo-box-option.element.js.map +1 -0
  92. package/target/lib/combo-box/combo-box.element.d.ts +22 -0
  93. package/target/lib/combo-box/combo-box.element.js +209 -0
  94. package/target/lib/combo-box/combo-box.element.js.map +1 -0
  95. package/target/lib/combo-box/combo-box.stories.d.ts +12 -0
  96. package/target/lib/combo-box/combo-box.stories.js +229 -0
  97. package/target/lib/combo-box/combo-box.stories.js.map +1 -0
  98. package/target/lib/combo-box/combo-box.test.d.ts +3 -0
  99. package/target/lib/combo-box/combo-box.test.js +88 -0
  100. package/target/lib/combo-box/combo-box.test.js.map +1 -0
  101. package/target/lib/combo-box/context.d.ts +6 -0
  102. package/target/lib/combo-box/context.js +3 -0
  103. package/target/lib/combo-box/context.js.map +1 -0
  104. package/target/lib/define.d.ts +3 -0
  105. package/target/lib/define.js +3 -0
  106. package/target/lib/define.js.map +1 -1
  107. package/target/lib/input/input.element.d.ts +1 -0
  108. package/target/lib/input/input.element.js +3 -0
  109. package/target/lib/input/input.element.js.map +1 -1
  110. package/target/lib/input/input.test.js +2 -3
  111. package/target/lib/input/input.test.js.map +1 -1
  112. package/target/lib/radio/radio-option/radio-option.element.js +2 -5
  113. package/target/lib/radio/radio-option/radio-option.element.js.map +1 -1
  114. package/target/lib/radio/radio.element.js.map +1 -1
  115. package/target/lib/radio/radio.stories.js.map +1 -1
  116. package/target/lib/range-slider/range-slider.element.d.ts +16 -0
  117. package/target/lib/range-slider/range-slider.element.js +146 -0
  118. package/target/lib/range-slider/range-slider.element.js.map +1 -0
  119. package/target/lib/range-slider/range-slider.stories.d.ts +12 -0
  120. package/target/lib/range-slider/range-slider.stories.js +17 -0
  121. package/target/lib/range-slider/range-slider.stories.js.map +1 -0
  122. package/target/lib/range-slider/range-slider.test.d.ts +1 -0
  123. package/target/lib/range-slider/range-slider.test.js +39 -0
  124. package/target/lib/range-slider/range-slider.test.js.map +1 -0
  125. package/target/lib/select/select.stories.d.ts +1 -1
  126. package/target/lib/select/select.stories.js +1 -1
  127. package/target/lib/select/select.stories.js.map +1 -1
  128. package/target/lib/select/select.test.js +2 -3
  129. package/target/lib/select/select.test.js.map +1 -1
  130. package/target/lib/side-nav/side-nav.stories.d.ts +1 -1
  131. package/target/lib/side-nav/side-nav.stories.js +1 -1
  132. package/target/lib/side-nav/side-nav.stories.js.map +1 -1
  133. package/target/lib/summary-box/summary-box.stories.d.ts +1 -1
  134. package/target/lib/summary-box/summary-box.stories.js +1 -1
  135. package/target/lib/summary-box/summary-box.stories.js.map +1 -1
  136. package/target/lib/textarea/textarea.test.js +2 -3
  137. package/target/lib/textarea/textarea.test.js.map +1 -1
  138. package/target/lib.d.ts +3 -0
  139. package/target/lib.js +3 -0
  140. package/target/lib.js.map +1 -1
  141. package/target/lib/form/validation.d.ts +0 -2
  142. package/target/lib/form/validation.js +0 -27
  143. package/target/lib/form/validation.js.map +0 -1
@@ -0,0 +1,236 @@
1
+ import type { Meta, StoryObj } from "@storybook/web-components";
2
+ import { html } from "lit";
3
+
4
+ import type { USAComboBoxElement } from "./combo-box.element.js";
5
+
6
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
7
+ const meta = {
8
+ title: "usa-combo-box",
9
+ tags: ["autodocs"],
10
+ render() {
11
+ return html`
12
+ <usa-combo-box>
13
+ <usa-input
14
+ placeholder="Select a state"
15
+ name="state"
16
+ slot="input"
17
+ autocomplete="off"
18
+ detail="sfx">
19
+ States
20
+ <usa-icon slot="detail" icon="expand_more"></usa-icon>
21
+ </usa-input>
22
+
23
+ <usa-combo-box-option value="Alabama">
24
+ <img src="/assets/flags/alabama.svg" alt="Alabama" height="20" /> Alabama
25
+ </usa-combo-box-option>
26
+
27
+ <usa-combo-box-option value="Alaska">
28
+ <img src="/assets/flags/alaska.svg" alt="Alaska" height="20" /> Alaska
29
+ </usa-combo-box-option>
30
+
31
+ <usa-combo-box-option value="Arizona">
32
+ <img src="/assets/flags/arizona.svg" alt="Arizona" height="20" /> Arizona
33
+ </usa-combo-box-option>
34
+
35
+ <usa-combo-box-option value="Arkansas">
36
+ <img src="/assets/flags/arkansas.svg" alt="Arkansas" height="20" /> Arkansas
37
+ </usa-combo-box-option>
38
+
39
+ <usa-combo-box-option value="California">
40
+ <img src="/assets/flags/california.svg" alt="California" height="20" /> California
41
+ </usa-combo-box-option>
42
+
43
+ <usa-combo-box-option value="Colorado">
44
+ <img src="/assets/flags/colorado.svg" alt="Colorado" height="20" /> Colorado
45
+ </usa-combo-box-option>
46
+
47
+ <usa-combo-box-option value="Connecticut">
48
+ <img src="/assets/flags/connecticut.svg" alt="Connecticut" height="20" /> Connecticut
49
+ </usa-combo-box-option>
50
+
51
+ <usa-combo-box-option value="Delaware">
52
+ <img src="/assets/flags/delaware.svg" alt="Delaware" height="20" /> Delaware
53
+ </usa-combo-box-option>
54
+
55
+ <usa-combo-box-option value="Florida">
56
+ <img src="/assets/flags/florida.svg" alt="Florida" height="20" /> Florida
57
+ </usa-combo-box-option>
58
+
59
+ <usa-combo-box-option value="Georgia">
60
+ <img src="/assets/flags/georgia.svg" alt="Georgia" height="20" /> Georgia
61
+ </usa-combo-box-option>
62
+
63
+ <usa-combo-box-option value="Hawaii">
64
+ <img src="/assets/flags/hawaii.svg" alt="Hawaii" height="20" /> Hawaii
65
+ </usa-combo-box-option>
66
+
67
+ <usa-combo-box-option value="Idaho">
68
+ <img src="/assets/flags/idaho.svg" alt="Idaho" height="20" /> Idaho
69
+ </usa-combo-box-option>
70
+
71
+ <usa-combo-box-option value="Illinois">
72
+ <img src="/assets/flags/illinois.svg" alt="Illinois" height="20" /> Illinois
73
+ </usa-combo-box-option>
74
+
75
+ <usa-combo-box-option value="Indiana">
76
+ <img src="/assets/flags/indiana.svg" alt="Indiana" height="20" /> Indiana
77
+ </usa-combo-box-option>
78
+
79
+ <usa-combo-box-option value="Iowa">
80
+ <img src="/assets/flags/iowa.svg" alt="Iowa" height="20" /> Iowa
81
+ </usa-combo-box-option>
82
+
83
+ <usa-combo-box-option value="Kansas">
84
+ <img src="/assets/flags/kansas.svg" alt="Kansas" height="20" /> Kansas
85
+ </usa-combo-box-option>
86
+
87
+ <usa-combo-box-option value="Kentucky">
88
+ <img src="/assets/flags/kentucky.svg" alt="Kentucky" height="20" /> Kentucky
89
+ </usa-combo-box-option>
90
+
91
+ <usa-combo-box-option value="Louisiana">
92
+ <img src="/assets/flags/louisiana.svg" alt="Louisiana" height="20" /> Louisiana
93
+ </usa-combo-box-option>
94
+
95
+ <usa-combo-box-option value="Maine">
96
+ <img src="/assets/flags/maine.svg" alt="Maine" height="20" /> Maine
97
+ </usa-combo-box-option>
98
+
99
+ <usa-combo-box-option value="Maryland">
100
+ <img src="/assets/flags/maryland.svg" alt="Maryland" height="20" /> Maryland
101
+ </usa-combo-box-option>
102
+
103
+ <usa-combo-box-option value="Massachusetts">
104
+ <img src="/assets/flags/massachusetts.svg" alt="Massachusetts" height="20" /> Massachusetts
105
+ </usa-combo-box-option>
106
+
107
+ <usa-combo-box-option value="Michigan">
108
+ <img src="/assets/flags/michigan.svg" alt="Michigan" height="20" /> Michigan
109
+ </usa-combo-box-option>
110
+
111
+ <usa-combo-box-option value="Minnesota">
112
+ <img src="/assets/flags/minnesota.svg" alt="Minnesota" height="20" /> Minnesota
113
+ </usa-combo-box-option>
114
+
115
+ <usa-combo-box-option value="Mississippi">
116
+ <img src="/assets/flags/mississippi.svg" alt="Mississippi" height="20" /> Mississippi
117
+ </usa-combo-box-option>
118
+
119
+ <usa-combo-box-option value="Missouri">
120
+ <img src="/assets/flags/missouri.svg" alt="Missouri" height="20" /> Missouri
121
+ </usa-combo-box-option>
122
+
123
+ <usa-combo-box-option value="Montana">
124
+ <img src="/assets/flags/montana.svg" alt="Montana" height="20" /> Montana
125
+ </usa-combo-box-option>
126
+
127
+ <usa-combo-box-option value="Nebraska">
128
+ <img src="/assets/flags/nebraska.svg" alt="Nebraska" height="20" /> Nebraska
129
+ </usa-combo-box-option>
130
+
131
+ <usa-combo-box-option value="Nevada">
132
+ <img src="/assets/flags/nevada.svg" alt="Nevada" height="20" /> Nevada
133
+ </usa-combo-box-option>
134
+
135
+ <usa-combo-box-option value="New Hampshire">
136
+ <img src="/assets/flags/new_hampshire.svg" alt="New Hampshire" height="20" /> New Hampshire
137
+ </usa-combo-box-option>
138
+
139
+ <usa-combo-box-option value="New Jersey">
140
+ <img src="/assets/flags/new_jersey.svg" alt="New Jersey" height="20" /> New Jersey
141
+ </usa-combo-box-option>
142
+
143
+ <usa-combo-box-option value="New Mexico">
144
+ <img src="/assets/flags/new_mexico.svg" alt="New Mexico" height="20" /> New Mexico
145
+ </usa-combo-box-option>
146
+
147
+ <usa-combo-box-option value="New York">
148
+ <img src="/assets/flags/new_york.svg" alt="New York" height="20" /> New York
149
+ </usa-combo-box-option>
150
+
151
+ <usa-combo-box-option value="North Carolina">
152
+ <img src="/assets/flags/north_carolina.svg" alt="North Carolina" height="20" /> North Carolina
153
+ </usa-combo-box-option>
154
+
155
+ <usa-combo-box-option value="North Dakota">
156
+ <img src="/assets/flags/north_dakota.svg" alt="North Dakota" height="20" /> North Dakota
157
+ </usa-combo-box-option>
158
+
159
+ <usa-combo-box-option value="Ohio">
160
+ <img src="/assets/flags/ohio.svg" alt="Ohio" height="20" /> Ohio
161
+ </usa-combo-box-option>
162
+
163
+ <usa-combo-box-option value="Oklahoma">
164
+ <img src="/assets/flags/oklahoma.svg" alt="Oklahoma" height="20" /> Oklahoma
165
+ </usa-combo-box-option>
166
+
167
+ <usa-combo-box-option value="Oregon">
168
+ <img src="/assets/flags/oregon.svg" alt="Oregon" height="20" /> Oregon
169
+ </usa-combo-box-option>
170
+
171
+ <usa-combo-box-option value="Pennsylvania">
172
+ <img src="/assets/flags/pennsylvania.svg" alt="Pennsylvania" height="20" /> Pennsylvania
173
+ </usa-combo-box-option>
174
+
175
+ <usa-combo-box-option value="Rhode Island">
176
+ <img src="/assets/flags/rhode_island.svg" alt="Rhode Island" height="20" /> Rhode Island
177
+ </usa-combo-box-option>
178
+
179
+ <usa-combo-box-option value="South Carolina">
180
+ <img src="/assets/flags/south_carolina.svg" alt="South Carolina" height="20" /> South Carolina
181
+ </usa-combo-box-option>
182
+
183
+ <usa-combo-box-option value="South Dakota">
184
+ <img src="/assets/flags/south_dakota.svg" alt="South Dakota" height="20" /> South Dakota
185
+ </usa-combo-box-option>
186
+
187
+ <usa-combo-box-option value="Tennessee">
188
+ <img src="/assets/flags/tennessee.svg" alt="Tennessee" height="20" /> Tennessee
189
+ </usa-combo-box-option>
190
+
191
+ <usa-combo-box-option value="Texas">
192
+ <img src="/assets/flags/texas.svg" alt="Texas" height="20" /> Texas
193
+ </usa-combo-box-option>
194
+
195
+ <usa-combo-box-option value="Utah">
196
+ <img src="/assets/flags/utah.svg" alt="Utah" height="20" /> Utah
197
+ </usa-combo-box-option>
198
+
199
+ <usa-combo-box-option value="Vermont">
200
+ <img src="/assets/flags/vermont.svg" alt="Vermont" height="20" /> Vermont
201
+ </usa-combo-box-option>
202
+
203
+ <usa-combo-box-option value="Virginia">
204
+ <img src="/assets/flags/virginia.svg" alt="Virginia" height="20" /> Virginia
205
+ </usa-combo-box-option>
206
+
207
+ <usa-combo-box-option value="Washington">
208
+ <img src="/assets/flags/washington.svg" alt="Washington" height="20" /> Washington
209
+ </usa-combo-box-option>
210
+
211
+ <usa-combo-box-option value="West Virginia">
212
+ <img src="/assets/flags/west_virginia.svg" alt="West Virginia" height="20" /> West Virginia
213
+ </usa-combo-box-option>
214
+
215
+ <usa-combo-box-option value="Wisconsin">
216
+ <img src="/assets/flags/wisconsin.svg" alt="Wisconsin" height="20" /> Wisconsin
217
+ </usa-combo-box-option>
218
+
219
+ <usa-combo-box-option value="Wyoming">
220
+ <img src="/assets/flags/wyoming.svg" alt="Wyoming" height="20" /> Wyoming
221
+ </usa-combo-box-option>
222
+ </usa-combo-box>
223
+ `;
224
+ },
225
+ argTypes: {},
226
+ args: {},
227
+ } satisfies Meta<USAComboBoxElement>;
228
+
229
+ export default meta;
230
+
231
+ type Story = StoryObj<USAComboBoxElement>;
232
+
233
+ // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
234
+ export const Primary: Story = {
235
+ args: {},
236
+ };
@@ -0,0 +1,150 @@
1
+ import "./combo-box.element.js";
2
+ import "./combo-box-option/combo-box-option.element.js";
3
+ import "../input/input.element.js";
4
+
5
+ import { assert, fixture, html } from "@open-wc/testing";
6
+
7
+ import type { USATextInputElement } from "../input/input.element.js";
8
+ import type { USAComboBoxElement } from "./combo-box.element.js";
9
+
10
+ describe("usa-combo-box", () => {
11
+ let autocomplete: USAComboBoxElement;
12
+ let input: USATextInputElement;
13
+
14
+ beforeEach(async () => {
15
+ autocomplete = await fixture<USAComboBoxElement>(html`
16
+ <usa-combo-box>
17
+ <usa-input slot="input" name="search"></usa-input>
18
+
19
+ <usa-combo-box-option value="Apple"></usa-combo-box-option>
20
+ <usa-combo-box-option value="Banana"></usa-combo-box-option>
21
+ <usa-combo-box-option value="Blueberry"></usa-combo-box-option>
22
+ <usa-combo-box-option value="Cherry"></usa-combo-box-option>
23
+ </usa-combo-box>
24
+ `);
25
+
26
+ const inputElement = autocomplete.querySelector("usa-input");
27
+
28
+ if (!inputElement) {
29
+ throw new Error("Input element not found");
30
+ }
31
+
32
+ input = inputElement;
33
+ });
34
+
35
+ it("should filter items based on input", async () => {
36
+ input.value = "b";
37
+ input.dispatchEvent(new Event("input", { bubbles: true }));
38
+
39
+ const suggestions = autocomplete.listItems();
40
+
41
+ assert.equal(suggestions.length, 2);
42
+ assert.equal(suggestions[0].dataset.value, "Banana");
43
+ assert.equal(suggestions[1].dataset.value, "Blueberry");
44
+ });
45
+
46
+ it("should show all suggestions when input is empty", async () => {
47
+ input.value = "";
48
+ input.dispatchEvent(new Event("input", { bubbles: true }));
49
+
50
+ const suggestions = autocomplete.listItems();
51
+ assert.equal(suggestions.length, 4);
52
+ });
53
+
54
+ it("should handle case-insensitive search", async () => {
55
+ input.value = "B";
56
+ input.dispatchEvent(new Event("input", { bubbles: true }));
57
+
58
+ const suggestions = autocomplete.listItems();
59
+ assert.equal(suggestions.length, 2);
60
+ assert.equal(suggestions[0].dataset.value, "Banana");
61
+ assert.equal(suggestions[1].dataset.value, "Blueberry");
62
+ });
63
+
64
+ it("should navigate suggestions with arrow keys", async () => {
65
+ // select item from list
66
+ input.value = "b";
67
+ input.dispatchEvent(new Event("input", { bubbles: true }));
68
+
69
+ // Arrow down
70
+ input.dispatchEvent(
71
+ new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
72
+ );
73
+ assert.equal(
74
+ autocomplete.currentItemEl?.getAttribute("data-value"),
75
+ "Banana",
76
+ );
77
+
78
+ // Arrow down again
79
+ input.dispatchEvent(
80
+ new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
81
+ );
82
+ assert.equal(
83
+ autocomplete.currentItemEl?.getAttribute("data-value"),
84
+ "Blueberry",
85
+ );
86
+ });
87
+
88
+ it("should select suggestion with enter key", async () => {
89
+ input.value = "b";
90
+ input.dispatchEvent(new Event("input", { bubbles: true }));
91
+
92
+ // Navigate to first suggestion
93
+ input.dispatchEvent(
94
+ new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
95
+ );
96
+
97
+ // Select suggestion
98
+ const firstSuggestion = autocomplete.listItems()[0];
99
+
100
+ firstSuggestion?.dispatchEvent(
101
+ new KeyboardEvent("keydown", { key: "Enter", bubbles: true }),
102
+ );
103
+
104
+ assert.equal(input.value, "Banana");
105
+ assert.equal(autocomplete.list().innerHTML, "");
106
+ });
107
+
108
+ it("should focus back on the input if no other items", async () => {
109
+ input.value = "b";
110
+ input.dispatchEvent(new Event("input", { bubbles: true }));
111
+
112
+ input.dispatchEvent(
113
+ new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
114
+ );
115
+
116
+ // Try to go up from first suggestion
117
+ input.dispatchEvent(
118
+ new KeyboardEvent("keydown", { key: "ArrowUp", bubbles: true }),
119
+ );
120
+
121
+ assert.equal(autocomplete.currentItemEl, null);
122
+ });
123
+
124
+ it("should not go below last suggestion with arrow down", async () => {
125
+ input.value = "b";
126
+ input.dispatchEvent(new Event("input", { bubbles: true }));
127
+
128
+ // Navigate to last suggestion
129
+ input.dispatchEvent(
130
+ new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
131
+ );
132
+
133
+ input.dispatchEvent(
134
+ new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
135
+ );
136
+
137
+ input.dispatchEvent(
138
+ new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
139
+ );
140
+
141
+ input.dispatchEvent(
142
+ new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
143
+ );
144
+
145
+ assert.equal(
146
+ autocomplete.currentItemEl?.getAttribute("data-value"),
147
+ "Blueberry",
148
+ );
149
+ });
150
+ });
@@ -0,0 +1,10 @@
1
+ import { StaticToken } from "@joist/di";
2
+
3
+ export interface ComboBoxContainer extends Node {
4
+ addOption(el: HTMLLIElement): void;
5
+ removeOption(el: HTMLLIElement): void;
6
+ }
7
+
8
+ export const COMBO_BOX_CTX = new StaticToken<ComboBoxContainer>(
9
+ "COMBO_BOX_CTX",
10
+ );
package/src/lib/define.ts CHANGED
@@ -33,3 +33,6 @@ import "./textarea/textarea.element.js";
33
33
  import "./collection/collection.element.js";
34
34
  import "./collection/collection-item/collection-item.element.js";
35
35
  import "./checkbox/checkbox-group/checkbox-group.element.js";
36
+ import "./range-slider/range-slider.element.js";
37
+ import "./combo-box/combo-box.element.js";
38
+ import "./combo-box/combo-box-option/combo-box-option.element.js";
@@ -163,6 +163,10 @@ export class USATextInputElement
163
163
  this.#syncFormState();
164
164
  }
165
165
 
166
+ focus(options?: FocusOptions): void {
167
+ this.#input().focus(options);
168
+ }
169
+
166
170
  @effect()
167
171
  onChange() {
168
172
  const { value, selectionStart, selectionEnd } = this;
@@ -1,7 +1,7 @@
1
1
  import "./input.element.js";
2
2
 
3
- import { fireEvent } from "@noctuatech-uswds/testing";
4
3
  import { assert, fixture, html } from "@open-wc/testing";
4
+ import { userEvent } from "@testing-library/user-event";
5
5
 
6
6
  describe("usa-input", () => {
7
7
  it("should be accessible", async () => {
@@ -39,9 +39,7 @@ describe("usa-input", () => {
39
39
  const nativeInput = input?.shadowRoot?.querySelector("input");
40
40
 
41
41
  if (nativeInput) {
42
- nativeInput.value = "Bar";
43
-
44
- await fireEvent.input(nativeInput, { bubbles: true });
42
+ await userEvent.type(nativeInput, "Bar");
45
43
  }
46
44
 
47
45
  const value = new FormData(form);
@@ -1,6 +1,6 @@
1
+ import { inject, injectable, injected } from "@joist/di";
1
2
  import { attr, css, element, html, query } from "@joist/element";
2
3
 
3
- import { inject, injectable, injected } from "@joist/di";
4
4
  import { RADIO_CTX } from "../context.js";
5
5
 
6
6
  declare global {
@@ -50,11 +50,7 @@ export class USARadioOptionElement extends HTMLElement {
50
50
  });
51
51
 
52
52
  attributeChangedCallback() {
53
- this.#input({
54
- value: this.value,
55
- disabled: this.disabled,
56
- });
57
-
53
+ this.#input({ value: this.value, disabled: this.disabled });
58
54
  this.#slot({ name: this.value });
59
55
 
60
56
  this.slot = this.value;
@@ -1,5 +1,5 @@
1
1
  import { injectable } from "@joist/di";
2
- import { attr, css, element, html, listen, query } from "@joist/element";
2
+ import { attr, css, element, html, listen } from "@joist/element";
3
3
 
4
4
  import { RADIO_CTX, type RadioContainer } from "./context.js";
5
5
 
@@ -1,7 +1,6 @@
1
1
  import type { Meta, StoryObj } from "@storybook/web-components";
2
2
  import { html } from "lit";
3
3
 
4
- import { when } from "lit/directives/when.js";
5
4
  import type { USARadioElement } from "./radio.element.js";
6
5
 
7
6
  // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
@@ -0,0 +1,111 @@
1
+ import { attr, css, element, html, listen, query } from "@joist/element";
2
+
3
+ declare global {
4
+ interface HTMLElementTagNameMap {
5
+ "usa-range-slider": USARangeSliderElement;
6
+ }
7
+ }
8
+
9
+ @element({
10
+ tagName: "usa-range-slider",
11
+ shadowDom: [
12
+ css`
13
+ :host {
14
+ display: flex;
15
+ flex-direction: column;
16
+ max-width: 30rem;
17
+ }
18
+
19
+ input {
20
+ height: 2.5rem;
21
+ -webkit-appearance: none; /* Hides the slider so that custom slider can be made */
22
+ width: 100%; /* Specific width is required for Firefox. */
23
+ background: transparent; /* Otherwise white in Chrome */
24
+ border-radius: 0;
25
+ color: #1b1b1b;
26
+ display: block;
27
+ margin-top: .5rem;
28
+ }
29
+
30
+ input:focus {
31
+ outline: .25rem solid #2491ff;
32
+ outline-offset: 0;
33
+ }
34
+
35
+ input::-webkit-slider-thumb {
36
+ height: 1.25rem;
37
+ border-radius: 99rem;
38
+ width: 1.25rem;
39
+ background: #f0f0f0;
40
+ border: 0;
41
+ box-shadow: 0 0 0 2px #757575;
42
+ cursor: pointer;
43
+ -webkit-appearance: none;
44
+ appearance: none;
45
+ margin-top: -.19rem;
46
+ }
47
+
48
+ input::-webkit-slider-runnable-track {
49
+ background-color: #f0f0f0;
50
+ border-radius: 99rem;
51
+ border: 1px solid #757575;
52
+ cursor: pointer;
53
+ height: 1rem;
54
+ width: 100%;
55
+ }
56
+ `,
57
+ html`
58
+ <label>
59
+ <slot></slot>
60
+ </label>
61
+
62
+ <input type="range">
63
+ `,
64
+ ],
65
+ })
66
+ export class USARangeSliderElement extends HTMLElement {
67
+ static formAssociated = true;
68
+
69
+ @attr()
70
+ accessor name = "";
71
+
72
+ @attr()
73
+ accessor value = "0";
74
+
75
+ @attr()
76
+ accessor min = "0";
77
+
78
+ @attr()
79
+ accessor max = "100";
80
+
81
+ @attr()
82
+ accessor step = "1";
83
+
84
+ #label = query("label");
85
+ #input = query("input");
86
+ #internals = this.attachInternals();
87
+
88
+ attributeChangedCallback() {
89
+ this.#label({
90
+ htmlFor: this.name,
91
+ });
92
+
93
+ this.#input({
94
+ name: this.name,
95
+ value: this.value,
96
+ min: this.min,
97
+ max: this.max,
98
+ step: this.step,
99
+ id: this.name,
100
+ });
101
+
102
+ this.#internals.setFormValue(this.value);
103
+ }
104
+
105
+ @listen("change")
106
+ onInputChange() {
107
+ const input = this.#input();
108
+
109
+ this.value = input.value;
110
+ }
111
+ }
@@ -0,0 +1,24 @@
1
+ import type { Meta, StoryObj } from "@storybook/web-components";
2
+ import { html } from "lit";
3
+
4
+ import type { USARangeSliderElement } from "./range-slider.element.js";
5
+
6
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
7
+ const meta = {
8
+ title: "usa-range-slider",
9
+ tags: ["autodocs"],
10
+ render(args) {
11
+ return html`<usa-range-slider name="test" value="50">Hello World</usa-range-slider>`;
12
+ },
13
+ argTypes: {},
14
+ args: {},
15
+ } satisfies Meta<USARangeSliderElement>;
16
+
17
+ export default meta;
18
+
19
+ type Story = StoryObj<USARangeSliderElement>;
20
+
21
+ // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
22
+ export const Primary: Story = {
23
+ args: {},
24
+ };
@@ -0,0 +1,52 @@
1
+ import "./range-slider.element.js";
2
+
3
+ import { assert, fixture, html } from "@open-wc/testing";
4
+ import { userEvent } from "@testing-library/user-event";
5
+
6
+ import type { USARangeSliderElement } from "./range-slider.element.js";
7
+
8
+ describe("usa-range-slider", () => {
9
+ it("should be accessible", async () => {
10
+ const rangeSlider = await fixture<USARangeSliderElement>(html`
11
+ <usa-range-slider name="slider" value="0">Hello World</usa-range-slider>
12
+ `);
13
+
14
+ return assert.isAccessible(rangeSlider);
15
+ });
16
+
17
+ it("should submit form with default values", async () => {
18
+ const form = await fixture<HTMLFormElement>(html`
19
+ <form>
20
+ <usa-range-slider name="slider" value="50">Hello World</usa-range-slider>
21
+
22
+ <button>Submit</button>
23
+ </form>
24
+ `);
25
+
26
+ const value = new FormData(form);
27
+
28
+ assert.equal(value.get("slider"), "50");
29
+ });
30
+
31
+ it("should update form value as input value changed", async () => {
32
+ const form = await fixture<HTMLFormElement>(html`
33
+ <form>
34
+ <usa-range-slider name="slider" value="50">Hello World</usa-range-slider>
35
+
36
+ <button>Submit</button>
37
+ </form>
38
+ `);
39
+
40
+ const input = form.querySelector("usa-input");
41
+ const nativeInput = input?.shadowRoot?.querySelector("input");
42
+
43
+ if (nativeInput) {
44
+ nativeInput.value = "75";
45
+ nativeInput.dispatchEvent(new Event("change"));
46
+ }
47
+
48
+ const value = new FormData(form);
49
+
50
+ assert.equal(value.get("slider"), "50");
51
+ });
52
+ });
@@ -7,7 +7,7 @@ import type { USASelectElement } from "./select.element.js";
7
7
  const meta = {
8
8
  title: "usa-select",
9
9
  tags: ["autodocs"],
10
- render(args) {
10
+ render() {
11
11
  return html`
12
12
  <usa-select value="third">
13
13
  Hello World