@noctuatech/uswds 1.3.2 → 1.3.4

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 (299) hide show
  1. package/package.json +5 -5
  2. package/src/lib/accordion/{accordion.test.ts → accordion.element.test.ts} +28 -31
  3. package/src/lib/accordion/accordion.element.ts +9 -7
  4. package/src/lib/alert/{alert.test.ts → alert.element.test.ts} +5 -6
  5. package/src/lib/alert/alert.element.ts +6 -4
  6. package/src/lib/breadcrumbs/breadcrumb/breadcrumb.element.ts +10 -10
  7. package/src/lib/breadcrumbs/breadcrumbs.element.test.ts +23 -0
  8. package/src/lib/button/button.element.test.ts +15 -0
  9. package/src/lib/button/button.element.ts +37 -42
  10. package/src/lib/button-group/button-group.element.test.ts +13 -0
  11. package/src/lib/card/{card.test.ts → card.element.test.ts} +12 -12
  12. package/src/lib/checkbox/{checkbox.test.ts → checkbox.element.test.ts} +15 -17
  13. package/src/lib/checkbox/checkbox.element.ts +28 -32
  14. package/src/lib/checkbox/checkbox.stories.ts +17 -33
  15. package/src/lib/collection/collection-item/collection-item.element.test.ts +15 -0
  16. package/src/lib/collection/collection.element.test.ts +13 -0
  17. package/src/lib/combo-box/{combo-box.test.ts → combo-box.element.test.ts} +64 -93
  18. package/src/lib/config/config.element.test.ts +13 -0
  19. package/src/lib/description/description.element.test.ts +13 -0
  20. package/src/lib/file-input/file-input-preview/file-input-preview.element.test.ts +93 -0
  21. package/src/lib/file-input/file-input-preview/file-input-preview.element.ts +15 -13
  22. package/src/lib/file-input/file-input.element.test.ts +73 -0
  23. package/src/lib/file-input/file-input.element.ts +10 -20
  24. package/src/lib/in-page-nav/in-page-nav-item/in-page-nav-item.element.ts +20 -20
  25. package/src/lib/in-page-nav/{in-page-nav.test.ts → in-page-nav.element.test.ts} +18 -21
  26. package/src/lib/input/{input.test.ts → input.element.test.ts} +11 -0
  27. package/src/lib/input/input.element.ts +57 -41
  28. package/src/lib/input-mask/input-mask.element.ts +1 -1
  29. package/src/lib/input-mask/input-mask.stories.ts +2 -0
  30. package/src/lib/link/link.element.ts +18 -25
  31. package/src/lib/modal/modal-close/modal-close.element.test.ts +13 -0
  32. package/src/lib/modal/modal-heading/modal-heading.element.test.ts +15 -0
  33. package/src/lib/modal/modal.element.test.ts +23 -0
  34. package/src/lib/pagination/pagination-item/pagination-item.element.ts +9 -6
  35. package/src/lib/pagination/pagination-no/pagination-no.element.ts +17 -17
  36. package/src/lib/pagination/pagination.element.test.ts +13 -0
  37. package/src/lib/process-list/{process-list.test.ts → process-list.element.test.ts} +19 -12
  38. package/src/lib/radio/radio-option/radio-option.element.test.ts +20 -0
  39. package/src/lib/radio/radio.element.test.ts +121 -0
  40. package/src/lib/range-slider/range-slider.element.test.ts +57 -0
  41. package/src/lib/range-slider/range-slider.element.ts +48 -33
  42. package/src/lib/search/search.element.test.ts +71 -0
  43. package/src/lib/select/{select.test.ts → select.element.test.ts} +23 -26
  44. package/src/lib/select/select.element.ts +31 -32
  45. package/src/lib/side-nav/{side-nav.test.ts → side-nav.element.test.ts} +13 -23
  46. package/src/lib/step-indicator/step/step.element.ts +16 -16
  47. package/src/lib/step-indicator/{step-indicator.test.ts → step-indicator.element.test.ts} +6 -6
  48. package/src/lib/summary-box/summary-box.element.test.ts +13 -0
  49. package/src/lib/tag/tag.element.test.ts +13 -0
  50. package/src/lib/textarea/{textarea.test.ts → textarea.element.test.ts} +13 -13
  51. package/src/lib/textarea/textarea.element.ts +23 -24
  52. package/target/lib/accordion/accordion.element.js +4 -2
  53. package/target/lib/accordion/accordion.element.js.map +1 -1
  54. package/target/lib/accordion/accordion.element.test.d.ts +1 -0
  55. package/target/lib/accordion/{accordion.test.js → accordion.element.test.js} +19 -19
  56. package/target/lib/accordion/accordion.element.test.js.map +1 -0
  57. package/target/lib/alert/alert.element.js +4 -2
  58. package/target/lib/alert/alert.element.js.map +1 -1
  59. package/target/lib/alert/alert.element.test.d.ts +1 -0
  60. package/target/lib/alert/{alert.test.js → alert.element.test.js} +5 -5
  61. package/target/lib/alert/alert.element.test.js.map +1 -0
  62. package/target/lib/breadcrumbs/breadcrumb/breadcrumb.element.d.ts +1 -1
  63. package/target/lib/breadcrumbs/breadcrumb/breadcrumb.element.js +6 -6
  64. package/target/lib/breadcrumbs/breadcrumbs.element.test.d.ts +2 -0
  65. package/target/lib/breadcrumbs/{breadcrumbs.test.js → breadcrumbs.element.test.js} +6 -6
  66. package/target/lib/breadcrumbs/breadcrumbs.element.test.js.map +1 -0
  67. package/target/lib/button/button.element.d.ts +3 -3
  68. package/target/lib/button/button.element.js +17 -23
  69. package/target/lib/button/button.element.js.map +1 -1
  70. package/target/lib/button/button.element.test.d.ts +1 -0
  71. package/target/lib/button/button.element.test.js +12 -0
  72. package/target/lib/button/button.element.test.js.map +1 -0
  73. package/target/lib/button-group/button-group.element.test.d.ts +1 -0
  74. package/target/lib/button-group/button-group.element.test.js +9 -0
  75. package/target/lib/button-group/button-group.element.test.js.map +1 -0
  76. package/target/lib/card/card.element.test.d.ts +6 -0
  77. package/target/lib/card/{card.test.js → card.element.test.js} +10 -10
  78. package/target/lib/card/card.element.test.js.map +1 -0
  79. package/target/lib/checkbox/checkbox.element.d.ts +3 -2
  80. package/target/lib/checkbox/checkbox.element.js +21 -22
  81. package/target/lib/checkbox/checkbox.element.js.map +1 -1
  82. package/target/lib/checkbox/checkbox.element.test.d.ts +1 -0
  83. package/target/lib/checkbox/{checkbox.test.js → checkbox.element.test.js} +13 -12
  84. package/target/lib/checkbox/checkbox.element.test.js.map +1 -0
  85. package/target/lib/checkbox/checkbox.stories.d.ts +2 -2
  86. package/target/lib/checkbox/checkbox.stories.js +6 -6
  87. package/target/lib/checkbox/checkbox.stories.js.map +1 -1
  88. package/target/lib/collection/collection-item/collection-item.element.test.d.ts +1 -0
  89. package/target/lib/collection/collection-item/collection-item.element.test.js +9 -0
  90. package/target/lib/collection/collection-item/collection-item.element.test.js.map +1 -0
  91. package/target/lib/collection/collection.element.test.d.ts +1 -0
  92. package/target/lib/collection/collection.element.test.js +9 -0
  93. package/target/lib/collection/collection.element.test.js.map +1 -0
  94. package/target/lib/combo-box/combo-box.element.test.d.ts +3 -0
  95. package/target/lib/combo-box/{combo-box.test.js → combo-box.element.test.js} +60 -60
  96. package/target/lib/combo-box/combo-box.element.test.js.map +1 -0
  97. package/target/lib/config/config.element.test.d.ts +1 -0
  98. package/target/lib/config/config.element.test.js +9 -0
  99. package/target/lib/config/config.element.test.js.map +1 -0
  100. package/target/lib/description/description.element.test.d.ts +1 -0
  101. package/target/lib/description/description.element.test.js +9 -0
  102. package/target/lib/description/description.element.test.js.map +1 -0
  103. package/target/lib/file-input/file-input-preview/file-input-preview.element.js +12 -10
  104. package/target/lib/file-input/file-input-preview/file-input-preview.element.js.map +1 -1
  105. package/target/lib/file-input/file-input-preview/file-input-preview.element.test.d.ts +2 -0
  106. package/target/lib/file-input/file-input-preview/{file-input-preview.test.js → file-input-preview.element.test.js} +24 -24
  107. package/target/lib/file-input/file-input-preview/file-input-preview.element.test.js.map +1 -0
  108. package/target/lib/file-input/file-input.element.js +5 -6
  109. package/target/lib/file-input/file-input.element.js.map +1 -1
  110. package/target/lib/file-input/file-input.element.test.d.ts +1 -0
  111. package/target/lib/file-input/{file-input.test.js → file-input.element.test.js} +16 -16
  112. package/target/lib/file-input/file-input.element.test.js.map +1 -0
  113. package/target/lib/in-page-nav/in-page-nav-item/in-page-nav-item.element.d.ts +2 -3
  114. package/target/lib/in-page-nav/in-page-nav-item/in-page-nav-item.element.js +15 -13
  115. package/target/lib/in-page-nav/in-page-nav-item/in-page-nav-item.element.js.map +1 -1
  116. package/target/lib/in-page-nav/in-page-nav.element.test.d.ts +2 -0
  117. package/target/lib/in-page-nav/{in-page-nav.test.js → in-page-nav.element.test.js} +6 -6
  118. package/target/lib/in-page-nav/in-page-nav.element.test.js.map +1 -0
  119. package/target/lib/input/input.element.d.ts +4 -5
  120. package/target/lib/input/input.element.js +54 -48
  121. package/target/lib/input/input.element.js.map +1 -1
  122. package/target/lib/input/{input.test.js → input.element.test.js} +6 -1
  123. package/target/lib/input/input.element.test.js.map +1 -0
  124. package/target/lib/input-mask/input-mask.element.d.ts +1 -1
  125. package/target/lib/input-mask/input-mask.element.js +1 -1
  126. package/target/lib/input-mask/input-mask.element.js.map +1 -1
  127. package/target/lib/input-mask/{input-mask.test.js → input-mask.element.test.js} +1 -1
  128. package/target/lib/input-mask/input-mask.element.test.js.map +1 -0
  129. package/target/lib/input-mask/input-mask.stories.js +1 -1
  130. package/target/lib/input-mask/input-mask.stories.js.map +1 -1
  131. package/target/lib/link/link.element.d.ts +3 -5
  132. package/target/lib/link/link.element.js +14 -26
  133. package/target/lib/link/link.element.js.map +1 -1
  134. package/target/lib/modal/modal-close/modal-close.element.test.d.ts +1 -0
  135. package/target/lib/modal/modal-close/modal-close.element.test.js +9 -0
  136. package/target/lib/modal/modal-close/modal-close.element.test.js.map +1 -0
  137. package/target/lib/modal/modal-heading/modal-heading.element.test.d.ts +1 -0
  138. package/target/lib/modal/modal-heading/modal-heading.element.test.js +9 -0
  139. package/target/lib/modal/modal-heading/modal-heading.element.test.js.map +1 -0
  140. package/target/lib/modal/modal.element.test.d.ts +3 -0
  141. package/target/lib/modal/modal.element.test.js +11 -0
  142. package/target/lib/modal/modal.element.test.js.map +1 -0
  143. package/target/lib/pagination/pagination-item/pagination-item.element.d.ts +1 -1
  144. package/target/lib/pagination/pagination-item/pagination-item.element.js +3 -3
  145. package/target/lib/pagination/pagination-item/pagination-item.element.js.map +1 -1
  146. package/target/lib/pagination/pagination-no/pagination-no.element.d.ts +2 -3
  147. package/target/lib/pagination/pagination-no/pagination-no.element.js +10 -8
  148. package/target/lib/pagination/pagination-no/pagination-no.element.js.map +1 -1
  149. package/target/lib/pagination/pagination.element.test.d.ts +1 -0
  150. package/target/lib/pagination/pagination.element.test.js +9 -0
  151. package/target/lib/pagination/pagination.element.test.js.map +1 -0
  152. package/target/lib/process-list/process-list.element.test.d.ts +2 -0
  153. package/target/lib/process-list/{process-list.test.js → process-list.element.test.js} +6 -6
  154. package/target/lib/process-list/process-list.element.test.js.map +1 -0
  155. package/target/lib/radio/radio-option/radio-option.element.test.d.ts +2 -0
  156. package/target/lib/radio/radio-option/radio-option.element.test.js +11 -0
  157. package/target/lib/radio/radio-option/radio-option.element.test.js.map +1 -0
  158. package/target/lib/radio/radio.element.test.d.ts +2 -0
  159. package/target/lib/radio/{radio.test.js → radio.element.test.js} +19 -28
  160. package/target/lib/radio/radio.element.test.js.map +1 -0
  161. package/target/lib/range-slider/range-slider.element.d.ts +4 -2
  162. package/target/lib/range-slider/range-slider.element.js +34 -29
  163. package/target/lib/range-slider/range-slider.element.js.map +1 -1
  164. package/target/lib/range-slider/range-slider.element.test.d.ts +1 -0
  165. package/target/lib/range-slider/range-slider.element.test.js +26 -0
  166. package/target/lib/range-slider/range-slider.element.test.js.map +1 -0
  167. package/target/lib/search/search.element.test.d.ts +3 -0
  168. package/target/lib/search/search.element.test.js +52 -0
  169. package/target/lib/search/search.element.test.js.map +1 -0
  170. package/target/lib/select/select.element.d.ts +4 -3
  171. package/target/lib/select/select.element.js +25 -26
  172. package/target/lib/select/select.element.js.map +1 -1
  173. package/target/lib/select/select.element.test.d.ts +2 -0
  174. package/target/lib/select/{select.test.js → select.element.test.js} +23 -27
  175. package/target/lib/select/select.element.test.js.map +1 -0
  176. package/target/lib/services/{icon.service.test.js → icon.service.element.test.js} +1 -1
  177. package/target/lib/services/icon.service.element.test.js.map +1 -0
  178. package/target/lib/side-nav/side-nav.element.test.d.ts +3 -0
  179. package/target/lib/side-nav/{side-nav.test.js → side-nav.element.test.js} +11 -11
  180. package/target/lib/side-nav/side-nav.element.test.js.map +1 -0
  181. package/target/lib/step-indicator/step/step.element.d.ts +2 -2
  182. package/target/lib/step-indicator/step/step.element.js +8 -8
  183. package/target/lib/step-indicator/step-indicator.element.test.d.ts +2 -0
  184. package/target/lib/step-indicator/{step-indicator.test.js → step-indicator.element.test.js} +6 -6
  185. package/target/lib/step-indicator/step-indicator.element.test.js.map +1 -0
  186. package/target/lib/summary-box/summary-box.element.test.d.ts +1 -0
  187. package/target/lib/summary-box/summary-box.element.test.js +9 -0
  188. package/target/lib/summary-box/summary-box.element.test.js.map +1 -0
  189. package/target/lib/tag/tag.element.test.d.ts +1 -0
  190. package/target/lib/tag/tag.element.test.js +9 -0
  191. package/target/lib/tag/tag.element.test.js.map +1 -0
  192. package/target/lib/textarea/textarea.element.d.ts +2 -2
  193. package/target/lib/textarea/textarea.element.js +19 -24
  194. package/target/lib/textarea/textarea.element.js.map +1 -1
  195. package/target/lib/textarea/textarea.element.test.d.ts +1 -0
  196. package/target/lib/textarea/{textarea.test.js → textarea.element.test.js} +14 -14
  197. package/target/lib/textarea/textarea.element.test.js.map +1 -0
  198. package/src/lib/breadcrumbs/breadcrumbs.test.ts +0 -21
  199. package/src/lib/button/button.test.ts +0 -17
  200. package/src/lib/button-group/button-group.test.ts +0 -15
  201. package/src/lib/collection/collection-item/collection-item.test.ts +0 -15
  202. package/src/lib/collection/collection.test.ts +0 -15
  203. package/src/lib/config/config.test.ts +0 -15
  204. package/src/lib/description/description.test.ts +0 -15
  205. package/src/lib/file-input/file-input-preview/file-input-preview.test.ts +0 -95
  206. package/src/lib/file-input/file-input.test.ts +0 -79
  207. package/src/lib/modal/modal-close/modal-close.test.ts +0 -15
  208. package/src/lib/modal/modal-heading/modal-heading.test.ts +0 -15
  209. package/src/lib/modal/modal.test.ts +0 -25
  210. package/src/lib/pagination/pagination.test.ts +0 -15
  211. package/src/lib/radio/radio-option/radio-option.test.ts +0 -20
  212. package/src/lib/radio/radio.test.ts +0 -174
  213. package/src/lib/range-slider/range-slider.test.ts +0 -52
  214. package/src/lib/search/search.test.ts +0 -81
  215. package/src/lib/summary-box/summary-box.test.ts +0 -15
  216. package/src/lib/tag/tag.test.ts +0 -15
  217. package/target/lib/accordion/accordion.test.d.ts +0 -1
  218. package/target/lib/accordion/accordion.test.js.map +0 -1
  219. package/target/lib/alert/alert.test.d.ts +0 -1
  220. package/target/lib/alert/alert.test.js.map +0 -1
  221. package/target/lib/breadcrumbs/breadcrumbs.test.d.ts +0 -2
  222. package/target/lib/breadcrumbs/breadcrumbs.test.js.map +0 -1
  223. package/target/lib/button/button.test.d.ts +0 -1
  224. package/target/lib/button/button.test.js +0 -12
  225. package/target/lib/button/button.test.js.map +0 -1
  226. package/target/lib/button-group/button-group.test.d.ts +0 -1
  227. package/target/lib/button-group/button-group.test.js +0 -9
  228. package/target/lib/button-group/button-group.test.js.map +0 -1
  229. package/target/lib/card/card.test.d.ts +0 -6
  230. package/target/lib/card/card.test.js.map +0 -1
  231. package/target/lib/checkbox/checkbox.test.d.ts +0 -1
  232. package/target/lib/checkbox/checkbox.test.js.map +0 -1
  233. package/target/lib/collection/collection-item/collection-item.test.d.ts +0 -1
  234. package/target/lib/collection/collection-item/collection-item.test.js +0 -9
  235. package/target/lib/collection/collection-item/collection-item.test.js.map +0 -1
  236. package/target/lib/collection/collection.test.d.ts +0 -1
  237. package/target/lib/collection/collection.test.js +0 -9
  238. package/target/lib/collection/collection.test.js.map +0 -1
  239. package/target/lib/combo-box/combo-box.test.d.ts +0 -3
  240. package/target/lib/combo-box/combo-box.test.js.map +0 -1
  241. package/target/lib/config/config.test.d.ts +0 -1
  242. package/target/lib/config/config.test.js +0 -9
  243. package/target/lib/config/config.test.js.map +0 -1
  244. package/target/lib/description/description.test.d.ts +0 -1
  245. package/target/lib/description/description.test.js +0 -9
  246. package/target/lib/description/description.test.js.map +0 -1
  247. package/target/lib/file-input/file-input-preview/file-input-preview.test.d.ts +0 -2
  248. package/target/lib/file-input/file-input-preview/file-input-preview.test.js.map +0 -1
  249. package/target/lib/file-input/file-input.test.d.ts +0 -1
  250. package/target/lib/file-input/file-input.test.js.map +0 -1
  251. package/target/lib/in-page-nav/in-page-nav.test.d.ts +0 -2
  252. package/target/lib/in-page-nav/in-page-nav.test.js.map +0 -1
  253. package/target/lib/input/input.test.js.map +0 -1
  254. package/target/lib/input-mask/input-mask.test.js.map +0 -1
  255. package/target/lib/modal/modal-close/modal-close.test.d.ts +0 -1
  256. package/target/lib/modal/modal-close/modal-close.test.js +0 -9
  257. package/target/lib/modal/modal-close/modal-close.test.js.map +0 -1
  258. package/target/lib/modal/modal-heading/modal-heading.test.d.ts +0 -1
  259. package/target/lib/modal/modal-heading/modal-heading.test.js +0 -9
  260. package/target/lib/modal/modal-heading/modal-heading.test.js.map +0 -1
  261. package/target/lib/modal/modal.test.d.ts +0 -3
  262. package/target/lib/modal/modal.test.js +0 -11
  263. package/target/lib/modal/modal.test.js.map +0 -1
  264. package/target/lib/pagination/pagination.test.d.ts +0 -1
  265. package/target/lib/pagination/pagination.test.js +0 -9
  266. package/target/lib/pagination/pagination.test.js.map +0 -1
  267. package/target/lib/process-list/process-list.test.d.ts +0 -2
  268. package/target/lib/process-list/process-list.test.js.map +0 -1
  269. package/target/lib/radio/radio-option/radio-option.test.d.ts +0 -2
  270. package/target/lib/radio/radio-option/radio-option.test.js +0 -11
  271. package/target/lib/radio/radio-option/radio-option.test.js.map +0 -1
  272. package/target/lib/radio/radio.test.d.ts +0 -2
  273. package/target/lib/radio/radio.test.js.map +0 -1
  274. package/target/lib/range-slider/range-slider.test.d.ts +0 -1
  275. package/target/lib/range-slider/range-slider.test.js +0 -25
  276. package/target/lib/range-slider/range-slider.test.js.map +0 -1
  277. package/target/lib/search/search.test.d.ts +0 -3
  278. package/target/lib/search/search.test.js +0 -52
  279. package/target/lib/search/search.test.js.map +0 -1
  280. package/target/lib/select/select.test.d.ts +0 -2
  281. package/target/lib/select/select.test.js.map +0 -1
  282. package/target/lib/services/icon.service.test.js.map +0 -1
  283. package/target/lib/side-nav/side-nav.test.d.ts +0 -3
  284. package/target/lib/side-nav/side-nav.test.js.map +0 -1
  285. package/target/lib/step-indicator/step-indicator.test.d.ts +0 -2
  286. package/target/lib/step-indicator/step-indicator.test.js.map +0 -1
  287. package/target/lib/summary-box/summary-box.test.d.ts +0 -1
  288. package/target/lib/summary-box/summary-box.test.js +0 -9
  289. package/target/lib/summary-box/summary-box.test.js.map +0 -1
  290. package/target/lib/tag/tag.test.d.ts +0 -1
  291. package/target/lib/tag/tag.test.js +0 -9
  292. package/target/lib/tag/tag.test.js.map +0 -1
  293. package/target/lib/textarea/textarea.test.d.ts +0 -1
  294. package/target/lib/textarea/textarea.test.js.map +0 -1
  295. /package/src/lib/input-mask/{input-mask.test.ts → input-mask.element.test.ts} +0 -0
  296. /package/src/lib/services/{icon.service.test.ts → icon.service.element.test.ts} +0 -0
  297. /package/target/lib/input/{input.test.d.ts → input.element.test.d.ts} +0 -0
  298. /package/target/lib/input-mask/{input-mask.test.d.ts → input-mask.element.test.d.ts} +0 -0
  299. /package/target/lib/services/{icon.service.test.d.ts → icon.service.element.test.d.ts} +0 -0
@@ -0,0 +1,93 @@
1
+ import './file-input-preview.element.js';
2
+ import '../../link/link.element.js';
3
+
4
+ import { assert, fixture, html } from '@open-wc/testing';
5
+
6
+ import type { USAFileInputPreviewElement } from './file-input-preview.element.js';
7
+
8
+ describe('usa-file-input-preview', () => {
9
+ it('should be accessible with no files', async () => {
10
+ const fileInputPreview = await fixture<USAFileInputPreviewElement>(html`
11
+ <usa-file-input-preview> Selected file <usa-link>Change file</usa-link> </usa-file-input-preview>
12
+ `);
13
+
14
+ return assert.isAccessible(fileInputPreview);
15
+ });
16
+
17
+ it('should be accessible with files', async () => {
18
+ const data = new DataTransfer();
19
+ data.items.add(new File([], 'image1.jpg'));
20
+ data.items.add(new File([], 'image2.jpg'));
21
+
22
+ const fileInputPreview = await fixture<USAFileInputPreviewElement>(html`
23
+ <usa-file-input-preview .files=${data.files}>
24
+ Selected file <usa-link>Change file</usa-link>
25
+ </usa-file-input-preview>
26
+ `);
27
+
28
+ return assert.isAccessible(fileInputPreview);
29
+ });
30
+
31
+ it('should display file preview for images', async () => {
32
+ const data = new DataTransfer();
33
+ data.items.add(new File([], 'image1.jpg'));
34
+ data.items.add(new File([], 'image2.jpg'));
35
+
36
+ const { shadowRoot } = await fixture<USAFileInputPreviewElement>(html`
37
+ <usa-file-input-preview .files=${data.files}>
38
+ Selected file <usa-link>Change file</usa-link>
39
+ </usa-file-input-preview>
40
+ `);
41
+
42
+ const previewItems = Array.from(shadowRoot?.querySelectorAll('.preview-item') ?? []).map((item) =>
43
+ item.textContent?.trim(),
44
+ );
45
+
46
+ assert.deepEqual(previewItems, ['image1.jpg', 'image2.jpg']);
47
+ });
48
+
49
+ it('should display fewer previews when the number of items decreases', async () => {
50
+ const data = new DataTransfer();
51
+ data.items.add(new File([], 'image1.jpg'));
52
+ data.items.add(new File([], 'image2.jpg'));
53
+
54
+ const fileInputPreview = await fixture<USAFileInputPreviewElement>(html`
55
+ <usa-file-input-preview .files=${data.files}>
56
+ Selected file <usa-link>Change file</usa-link>
57
+ </usa-file-input-preview>
58
+ `);
59
+
60
+ const data2 = new DataTransfer();
61
+ data2.items.add(new File([], 'image1.jpg'));
62
+
63
+ fileInputPreview.files = data2.files;
64
+
65
+ // need this to wait for effects to resolve
66
+ await Promise.resolve();
67
+
68
+ const previewItems = Array.from(fileInputPreview.shadowRoot?.querySelectorAll('.preview-item') ?? []).map((item) =>
69
+ item.textContent?.trim(),
70
+ );
71
+
72
+ assert.deepEqual(previewItems, ['image1.jpg']);
73
+ });
74
+
75
+ it('should create preview images for each file', async () => {
76
+ const data = new DataTransfer();
77
+ data.items.add(new File(['Image1'], 'image1.jpg', { type: 'image/jpg' }));
78
+ data.items.add(new File(['Image2'], 'image2.jpg', { type: 'image/jpg' }));
79
+
80
+ const { shadowRoot } = await fixture<USAFileInputPreviewElement>(html`
81
+ <usa-file-input-preview .files=${data.files}>
82
+ Selected file <usa-link>Change file</usa-link>
83
+ </usa-file-input-preview>
84
+ `);
85
+
86
+ const [first, second] = Array.from(shadowRoot?.querySelectorAll<HTMLImageElement>('.preview-item img') ?? []).map(
87
+ (item) => item.src.substring(29),
88
+ );
89
+
90
+ // we are just testing that the two hashes are in fact different
91
+ assert.isFalse(first === second);
92
+ });
93
+ });
@@ -77,9 +77,9 @@ declare global {
77
77
  <div class="preview-item" part="item">
78
78
  <j-if bind="each.value.isImage">
79
79
  <template>
80
- <j-props>
81
- <img height="40" width="40" aria-hidden="true" $.src="each.value.src" />
82
- </j-props>
80
+ <j-bind props="src:each.value.src">
81
+ <img height="40" width="40" aria-hidden="true" />
82
+ </j-bind>
83
83
  </template>
84
84
 
85
85
  <template else>
@@ -87,7 +87,7 @@ declare global {
87
87
  </template>
88
88
  </j-if>
89
89
 
90
- <j-value bind="each.value.file.name"></j-value>
90
+ <j-val bind="each.value.file.name"></j-val>
91
91
  </div>
92
92
  </template>
93
93
  </j-for>
@@ -98,16 +98,18 @@ export class USAFileInputPreviewElement extends HTMLElement {
98
98
  @observe()
99
99
  accessor files: FileList | null = null;
100
100
 
101
- @bind((i) => {
102
- if (!i.files || i.files.length === 0) {
103
- return [];
104
- }
101
+ @bind({
102
+ compute: (i) => {
103
+ if (!i.files || i.files.length === 0) {
104
+ return [];
105
+ }
105
106
 
106
- return Array.from(i.files).map((file) => ({
107
- file,
108
- src: URL.createObjectURL(file),
109
- isImage: file.type.startsWith('image'),
110
- }));
107
+ return Array.from(i.files).map((file) => ({
108
+ file,
109
+ src: URL.createObjectURL(file),
110
+ isImage: file.type.startsWith('image'),
111
+ }));
112
+ },
111
113
  })
112
114
  accessor fileEntries: FileEntry[] = [];
113
115
  }
@@ -0,0 +1,73 @@
1
+ import './file-input.element.js';
2
+
3
+ import { assert, fixture, html } from '@open-wc/testing';
4
+
5
+ import type { USAFileInputElement } from './file-input.element.js';
6
+
7
+ describe('usa-file-input', () => {
8
+ it('should be accessible', async () => {
9
+ const fileInput = await fixture<USAFileInputElement>(html` <usa-file-input>Hello World</usa-file-input> `);
10
+
11
+ return assert.isAccessible(fileInput);
12
+ });
13
+
14
+ it('should submit files with the form', async () => {
15
+ const data = new DataTransfer();
16
+ data.items.add(new File([], 'first.txt'));
17
+ data.items.add(new File([], 'second.txt'));
18
+
19
+ const form = await fixture<HTMLFormElement>(html`
20
+ <form>
21
+ <usa-file-input name="upload" .files=${data.files}>
22
+ Input accepts a single file
23
+
24
+ <div slot="description">Drag file here or <usa-link>choose from folder</usa-link></div>
25
+ </usa-file-input>
26
+
27
+ <button>Submit</button>
28
+ </form>
29
+ `);
30
+
31
+ const formData = new FormData(form);
32
+
33
+ const fileNames = formData.getAll('upload').map((file) => {
34
+ if (file instanceof File) {
35
+ return file.name;
36
+ }
37
+
38
+ return '';
39
+ });
40
+
41
+ assert.deepEqual(fileNames, ['first.txt', 'second.txt']);
42
+ });
43
+
44
+ it('should show file preview after drag and drop', async () => {
45
+ const fileInput = await fixture<USAFileInputElement>(html`
46
+ <usa-file-input> Input accepts a single file </usa-file-input>
47
+ `);
48
+
49
+ const nativeInput = fileInput.shadowRoot?.querySelector('input');
50
+
51
+ assert.isOk(nativeInput);
52
+
53
+ // Simulate drag and drop with a file
54
+ const data = new DataTransfer();
55
+ data.items.add(new File([], 'test.txt'));
56
+
57
+ const dropEvent = new DragEvent('drop', {
58
+ dataTransfer: data,
59
+ bubbles: true,
60
+ cancelable: true,
61
+ });
62
+
63
+ nativeInput.dispatchEvent(dropEvent);
64
+
65
+ // Wait for effects to resolve
66
+ await Promise.resolve();
67
+
68
+ // Verify that filesVisible is true and files are set
69
+ assert.isTrue(fileInput.filesVisible);
70
+ assert.equal(fileInput.files?.length, 1);
71
+ assert.equal(fileInput.files?.[0].name, 'test.txt');
72
+ });
73
+ });
@@ -82,25 +82,17 @@ declare global {
82
82
  </label>
83
83
 
84
84
  <div class="container">
85
- <j-props>
86
- <input
87
- id="file-input"
88
- type="file"
89
- tabindex="0"
90
- $.name="name"
91
- $.multiple="multiple"
92
- $.accept="accept"
93
- $.required="required"
94
- />
95
- </j-props>
85
+ <j-bind props="name,multiple,accept,required">
86
+ <input id="file-input" type="file" tabindex="0" />
87
+ </j-bind>
96
88
 
97
89
  <j-if bind="filesVisible">
98
90
  <template>
99
- <j-props>
100
- <usa-file-input-preview $.files="files" part="preview" exportparts="heading, item">
91
+ <j-bind props="files">
92
+ <usa-file-input-preview part="preview" exportparts="heading, item">
101
93
  Selected file&nbsp;<usa-link>Change file</usa-link>
102
94
  </usa-file-input-preview>
103
- </j-props>
95
+ </j-bind>
104
96
  </template>
105
97
 
106
98
  <template else>
@@ -135,18 +127,16 @@ export class USAFileInputElement extends HTMLElement {
135
127
  @bind()
136
128
  accessor files: FileList | null = null;
137
129
 
138
- @bind((i) => !!i.files?.length)
130
+ @bind({
131
+ compute: (i) => !!i.files?.length,
132
+ })
139
133
  accessor filesVisible = false;
140
134
 
141
135
  #internals = this.attachInternals();
142
136
  #input = query('input');
143
137
 
144
138
  connectedCallback() {
145
- const input = this.#input();
146
-
147
- if (input.validationMessage) {
148
- this.#internals.setValidity({ customError: true }, input.validationMessage, input);
149
- }
139
+ this.syncFormValues();
150
140
  }
151
141
 
152
142
  @effect()
@@ -1,26 +1,29 @@
1
- import { attr, css, element, html, listen, query } from "@joist/element";
1
+ import '@joist/templating/define.js';
2
+
3
+ import { attr, css, element, html, listen } from '@joist/element';
4
+ import { bind } from '@joist/templating';
2
5
 
3
6
  declare global {
4
7
  interface HTMLElementTagNameMap {
5
- "usa-in-page-nav-item": USAInPageNavItemElement;
8
+ 'usa-in-page-nav-item': USAInPageNavItemElement;
6
9
  }
7
10
  }
8
11
 
9
12
  @element({
10
- tagName: "usa-in-page-nav-item",
13
+ tagName: 'usa-in-page-nav-item',
11
14
  shadowDom: [
12
15
  css`
13
16
  :host {
14
- border-left: solid .25rem transparent;
17
+ border-left: solid 0.25rem transparent;
15
18
  display: flex;
16
- font-size: .93rem;
19
+ font-size: 0.93rem;
17
20
  line-height: 1.1;
18
21
  position: relative;
19
22
  }
20
23
 
21
24
  a {
22
25
  color: #005ea2;
23
- padding: .5rem 1rem;
26
+ padding: 0.5rem 1rem;
24
27
  text-decoration: none;
25
28
  }
26
29
 
@@ -42,21 +45,24 @@ declare global {
42
45
  }
43
46
  `,
44
47
  html`
45
- <a>
46
- <slot></slot>
47
- </a>
48
+ <j-bind props="href:target">
49
+ <a>
50
+ <slot></slot>
51
+ </a>
52
+ </j-bind>
48
53
  `,
49
54
  ],
50
55
  })
51
56
  export class USAInPageNavItemElement extends HTMLElement {
52
57
  @attr()
53
- accessor role = "listitem";
58
+ accessor role = 'listitem';
54
59
 
55
60
  @attr()
56
61
  accessor primary = false;
57
62
 
58
63
  @attr()
59
- accessor target = "";
64
+ @bind()
65
+ accessor target = '';
60
66
 
61
67
  @attr()
62
68
  accessor active = false;
@@ -65,20 +71,14 @@ export class USAInPageNavItemElement extends HTMLElement {
65
71
  return document.getElementById(this.target);
66
72
  }
67
73
 
68
- #a = query("a");
69
-
70
- attributeChangedCallback() {
71
- this.#a({ href: `#${this.target}` });
72
- }
73
-
74
- @listen("click")
74
+ @listen('click')
75
75
  async onClick(e: Event) {
76
76
  e.preventDefault();
77
77
 
78
78
  if (this.targetElement) {
79
- this.targetElement.scrollIntoView({ behavior: "smooth" });
79
+ this.targetElement.scrollIntoView({ behavior: 'smooth' });
80
80
  }
81
81
 
82
- history.pushState(null, "", `#${this.target}`);
82
+ history.pushState(null, '', `#${this.target}`);
83
83
  }
84
84
  }
@@ -1,38 +1,35 @@
1
- import "./in-page-nav.element.js";
2
- import "./in-page-nav-item/in-page-nav-item.element.js";
1
+ import './in-page-nav.element.js';
2
+ import './in-page-nav-item/in-page-nav-item.element.js';
3
3
 
4
- import { assert, fixture, html } from "@open-wc/testing";
4
+ import { assert, fixture, html } from '@open-wc/testing';
5
5
 
6
- import type { USAInPageNavElement } from "./in-page-nav.element.js";
6
+ import type { USAInPageNavElement } from './in-page-nav.element.js';
7
7
 
8
- describe("usa-in-page-nav", () => {
9
- it("should be accessible", async () => {
8
+ describe('usa-in-page-nav', () => {
9
+ it('should be accessible', async () => {
10
10
  const inPageNav = await fixture<USAInPageNavElement>(html`
11
11
  <usa-in-page-nav>
12
- <usa-in-page-nav-item target="lorem-ipsum-dolor" primary>
13
- Lorem ipsum dolor
14
- </usa-in-page-nav-item>
12
+ <usa-in-page-nav-item target="lorem-ipsum-dolor" primary>Lorem ipsum dolor</usa-in-page-nav-item>
13
+
15
14
  <usa-in-page-nav-item target="consectetuer-adipiscing-elit" primary>
16
15
  Consectetuer adipiscing elit
17
16
  </usa-in-page-nav-item>
18
- <usa-in-page-nav-item target="nullam-sit-amet-enim">
19
- Nullam sit amet enim
20
- </usa-in-page-nav-item>
17
+
18
+ <usa-in-page-nav-item target="nullam-sit-amet-enim">Nullam sit amet enim</usa-in-page-nav-item>
19
+
21
20
  <usa-in-page-nav-item target="vivamus-pharetra-posuere-sapien">
22
21
  Vivamus pharetra posuere sapien
23
22
  </usa-in-page-nav-item>
24
- <usa-in-page-nav-item target="suspendisse-id-velit">
25
- Suspendisse id velit
26
- </usa-in-page-nav-item>
27
- <usa-in-page-nav-item target="orci-magna-rhoncus-neque">
28
- Orci magna rhoncus neque
29
- </usa-in-page-nav-item>
23
+
24
+ <usa-in-page-nav-item target="suspendisse-id-velit">Suspendisse id velit</usa-in-page-nav-item>
25
+
26
+ <usa-in-page-nav-item target="orci-magna-rhoncus-neque">Orci magna rhoncus neque</usa-in-page-nav-item>
27
+
30
28
  <usa-in-page-nav-item target="aliquam-erat-volutpat-velit-vitae-ligula-volutpat" primary>
31
29
  Aliquam erat volutpat: velit vitae ligula volutpat
32
30
  </usa-in-page-nav-item>
33
- <usa-in-page-nav-item target="vitae-ligula">
34
- Vitae ligula
35
- </usa-in-page-nav-item>
31
+
32
+ <usa-in-page-nav-item target="vitae-ligula">Vitae ligula</usa-in-page-nav-item>
36
33
  </usa-in-page-nav>
37
34
  `);
38
35
 
@@ -2,6 +2,7 @@ import './input.element.js';
2
2
 
3
3
  import { assert, fixture, html } from '@open-wc/testing';
4
4
  import { userEvent } from '@testing-library/user-event';
5
+ import { USATextInputElement } from './input.element.js';
5
6
 
6
7
  describe('usa-input', () => {
7
8
  it('should be accessible', async () => {
@@ -24,6 +25,16 @@ describe('usa-input', () => {
24
25
  assert.equal(value.get('fname'), 'Foo');
25
26
  });
26
27
 
28
+ it('should display default attribute value', async () => {
29
+ const input = await fixture<USATextInputElement>(html`
30
+ <usa-input name="fname" value="Foo">Hello World</usa-input>
31
+ `);
32
+
33
+ const nativeInput = input.shadowRoot?.querySelector('input');
34
+
35
+ assert.equal(nativeInput?.value, 'Foo');
36
+ });
37
+
27
38
  it('should update form value as input value changed', async () => {
28
39
  const form = await fixture<HTMLFormElement>(html`
29
40
  <form>
@@ -1,5 +1,8 @@
1
- import { attr, css, element, html, listen, query, ready } from '@joist/element';
2
- import { effect, observe } from '@joist/observable';
1
+ import '@joist/templating/define.js';
2
+
3
+ import { attr, css, element, html, listen, query } from '@joist/element';
4
+ import { effect } from '@joist/observable';
5
+ import { bind } from '@joist/templating';
3
6
 
4
7
  import type { MaskableElement } from '../input-mask/maskable.element.js';
5
8
 
@@ -89,7 +92,26 @@ declare global {
89
92
 
90
93
  <slot></slot>
91
94
 
92
- <input tabindex="0" part="input" />
95
+ <j-bind
96
+ props="
97
+ autocomplete,
98
+ autofocus,
99
+ placeholder,
100
+ name,
101
+ type,
102
+ required,
103
+ min,
104
+ max,
105
+ minLength,
106
+ maxLength,
107
+ disabled,
108
+ value,
109
+ selectionStart,
110
+ selectionEnd
111
+ "
112
+ >
113
+ <input tabindex="0" part="input" />
114
+ </j-bind>
93
115
  </label>
94
116
  `,
95
117
  ],
@@ -98,94 +120,84 @@ export class USATextInputElement extends HTMLElement implements MaskableElement
98
120
  static formAssociated = true;
99
121
 
100
122
  @attr()
123
+ @bind()
101
124
  accessor name = '';
102
125
 
103
126
  @attr()
127
+ @bind()
104
128
  accessor autocomplete: AutoFill = 'on';
105
129
 
106
130
  @attr()
131
+ @bind()
107
132
  accessor placeholder = '';
108
133
 
109
134
  @attr()
135
+ @bind()
110
136
  accessor min = '';
111
137
 
112
138
  @attr()
139
+ @bind()
113
140
  accessor max = '';
114
141
 
115
142
  @attr()
116
- accessor minLength = -1;
143
+ @bind()
144
+ accessor minLength = 0;
117
145
 
118
146
  @attr()
119
- accessor maxLength = -1;
147
+ @bind()
148
+ accessor maxLength = 524_288;
120
149
 
121
150
  @attr()
151
+ @bind()
122
152
  accessor required = false;
123
153
 
124
154
  @attr()
155
+ @bind()
125
156
  accessor disabled = false;
126
157
 
127
158
  @attr()
159
+ @bind()
128
160
  accessor type: 'text' | 'password' | 'number' = 'text';
129
161
 
162
+ @attr()
163
+ @bind()
164
+ accessor autofocus = false;
165
+
130
166
  @attr()
131
167
  accessor detail: 'pfx' | 'sfx' | '' = '';
132
168
 
133
169
  @attr({
134
170
  reflect: false,
135
171
  })
136
- @observe()
172
+ @bind()
137
173
  accessor value = '';
138
174
 
139
- @observe()
175
+ @bind({
176
+ alwaysUpdate: true,
177
+ })
140
178
  accessor selectionStart: number | null = null;
141
179
 
142
- @observe()
180
+ @bind({
181
+ alwaysUpdate: true,
182
+ })
143
183
  accessor selectionEnd: number | null = null;
144
184
 
145
- get validationMessage() {
146
- return this.#input().validationMessage;
147
- }
148
-
149
185
  #internals = this.attachInternals();
150
186
  #input = query('input');
151
187
 
152
- @ready()
153
- onReady() {
154
- this.#input({ autofocus: this.autofocus });
155
- }
156
-
157
- attributeChangedCallback() {
158
- this.#input({
159
- autocomplete: this.autocomplete,
160
- placeholder: this.placeholder,
161
- name: this.name,
162
- type: this.type,
163
- required: this.required,
164
- min: this.min,
165
- max: this.max,
166
- minLength: this.minLength,
167
- maxLength: this.maxLength,
168
- disabled: this.disabled,
169
- });
170
- }
171
-
172
188
  connectedCallback() {
173
189
  this.#syncFormState();
174
190
  }
175
191
 
176
- focus(options?: FocusOptions): void {
177
- this.#input().focus(options);
178
- }
179
-
180
192
  @effect()
181
193
  onChange() {
182
- const { value, selectionStart, selectionEnd } = this;
183
-
184
- this.#input({ value, selectionStart, selectionEnd });
185
-
186
194
  this.#syncFormState();
187
195
  }
188
196
 
197
+ focus(options?: FocusOptions): void {
198
+ this.#input().focus(options);
199
+ }
200
+
189
201
  @listen('keydown')
190
202
  onKeyDown(e: KeyboardEvent) {
191
203
  const form = this.#internals.form;
@@ -205,12 +217,16 @@ export class USATextInputElement extends HTMLElement implements MaskableElement
205
217
  }
206
218
 
207
219
  @listen('input')
208
- onInputChange() {
220
+ onInputChange(e: Event) {
221
+ e.stopPropagation();
222
+
209
223
  const input = this.#input();
210
224
 
211
225
  this.value = input.value;
212
226
  this.selectionStart = input.selectionStart;
213
227
  this.selectionEnd = input.selectionEnd;
228
+
229
+ this.dispatchEvent(new Event('input', { bubbles: true }));
214
230
  }
215
231
 
216
232
  #syncFormState() {
@@ -37,7 +37,7 @@ export class USAInputMaskElement extends HTMLElement {
37
37
  }
38
38
 
39
39
  @listen('input')
40
- onInput(e: Event) {
40
+ async onInput(e: Event) {
41
41
  const input = e.target as MaskableElement;
42
42
  const selectionStart = input.selectionStart || 0;
43
43
  const prev = input.value;
@@ -13,6 +13,8 @@ const meta = {
13
13
  <usa-input name="phone" placeholder=${args.mask} autocomplete="off" mask=${args.mask} value="1234567890">
14
14
  Phone:
15
15
  </usa-input>
16
+
17
+ <input type="text" placeholder=${args.mask} autocomplete="off" mask=${args.mask} value="1234567890" />
16
18
  </usa-input-mask>
17
19
  `;
18
20
  },