@cfpb/cfpb-design-system 4.2.4 → 4.3.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.
Files changed (218) hide show
  1. package/CHANGELOG.md +186 -1
  2. package/dist/components/cfpb-buttons/index.css +1 -1
  3. package/dist/components/cfpb-buttons/index.css.map +2 -2
  4. package/dist/components/cfpb-buttons/index.js +1 -1
  5. package/dist/components/cfpb-buttons/index.js.map +1 -1
  6. package/dist/components/cfpb-expandables/index.css +1 -1
  7. package/dist/components/cfpb-expandables/index.css.map +2 -2
  8. package/dist/components/cfpb-expandables/index.js +1 -1
  9. package/dist/components/cfpb-expandables/index.js.map +4 -4
  10. package/dist/components/cfpb-forms/index.css +1 -1
  11. package/dist/components/cfpb-forms/index.css.map +2 -2
  12. package/dist/components/cfpb-forms/index.js +1 -1
  13. package/dist/components/cfpb-forms/index.js.map +2 -2
  14. package/dist/components/cfpb-icons/index.css +1 -1
  15. package/dist/components/cfpb-icons/index.css.map +2 -2
  16. package/dist/components/cfpb-icons/index.js +1 -1
  17. package/dist/components/cfpb-icons/index.js.map +1 -1
  18. package/dist/components/cfpb-layout/index.css +1 -1
  19. package/dist/components/cfpb-layout/index.css.map +2 -2
  20. package/dist/components/cfpb-layout/index.js +1 -1
  21. package/dist/components/cfpb-layout/index.js.map +1 -1
  22. package/dist/components/cfpb-notifications/index.css +1 -1
  23. package/dist/components/cfpb-notifications/index.css.map +2 -2
  24. package/dist/components/cfpb-notifications/index.js +1 -1
  25. package/dist/components/cfpb-notifications/index.js.map +1 -1
  26. package/dist/components/cfpb-pagination/index.css +1 -1
  27. package/dist/components/cfpb-pagination/index.css.map +2 -2
  28. package/dist/components/cfpb-pagination/index.js +1 -1
  29. package/dist/components/cfpb-pagination/index.js.map +1 -1
  30. package/dist/components/cfpb-tables/index.css +1 -1
  31. package/dist/components/cfpb-tables/index.css.map +2 -2
  32. package/dist/components/cfpb-tables/index.js +1 -1
  33. package/dist/components/cfpb-tables/index.js.map +1 -1
  34. package/dist/components/cfpb-tooltips/index.css +1 -1
  35. package/dist/components/cfpb-tooltips/index.css.map +2 -2
  36. package/dist/components/cfpb-tooltips/index.js +1 -1
  37. package/dist/components/cfpb-tooltips/index.js.map +1 -1
  38. package/dist/components/cfpb-typography/index.css +1 -1
  39. package/dist/components/cfpb-typography/index.css.map +2 -2
  40. package/dist/components/cfpb-typography/index.js +1 -1
  41. package/dist/components/cfpb-typography/index.js.map +1 -1
  42. package/dist/elements/abstracts/index.js +2 -0
  43. package/dist/elements/abstracts/index.js.map +7 -0
  44. package/dist/elements/base/index.css +3 -0
  45. package/dist/elements/base/index.css.map +7 -0
  46. package/dist/elements/base/index.js +2 -0
  47. package/dist/elements/base/index.js.map +7 -0
  48. package/dist/elements/cfpb-button/index.js +4 -4
  49. package/dist/elements/cfpb-button/index.js.map +3 -3
  50. package/dist/elements/cfpb-checkbox-icon/index.js +29 -0
  51. package/dist/elements/{cfpb-checkbox → cfpb-checkbox-icon}/index.js.map +4 -4
  52. package/dist/elements/cfpb-expandable/index.css +2 -0
  53. package/dist/elements/cfpb-expandable/index.css.map +7 -0
  54. package/dist/elements/cfpb-expandable/index.js +33 -0
  55. package/dist/elements/cfpb-expandable/index.js.map +7 -0
  56. package/dist/elements/cfpb-file-upload/index.js +4 -4
  57. package/dist/elements/cfpb-file-upload/index.js.map +3 -3
  58. package/dist/elements/cfpb-form-alert/index.js +32 -0
  59. package/dist/elements/cfpb-form-alert/index.js.map +7 -0
  60. package/dist/elements/cfpb-form-choice/index.js +12 -3
  61. package/dist/elements/cfpb-form-choice/index.js.map +4 -4
  62. package/dist/elements/cfpb-form-search/index.js +41 -0
  63. package/dist/elements/cfpb-form-search/index.js.map +7 -0
  64. package/dist/elements/cfpb-form-search-input/index.js +41 -0
  65. package/dist/elements/cfpb-form-search-input/index.js.map +7 -0
  66. package/dist/elements/cfpb-icon-text/index.js +3 -3
  67. package/dist/elements/cfpb-icon-text/index.js.map +3 -3
  68. package/dist/elements/cfpb-label/index.js +3 -3
  69. package/dist/elements/cfpb-label/index.js.map +2 -2
  70. package/dist/elements/cfpb-list/index.js +39 -0
  71. package/dist/elements/cfpb-list/index.js.map +7 -0
  72. package/dist/elements/cfpb-list-item/index.js +39 -0
  73. package/dist/elements/cfpb-list-item/index.js.map +7 -0
  74. package/dist/elements/cfpb-multiselect/index.js +13 -4
  75. package/dist/elements/cfpb-multiselect/index.js.map +4 -4
  76. package/dist/elements/cfpb-pagination/index.js +3 -3
  77. package/dist/elements/cfpb-pagination/index.js.map +2 -2
  78. package/dist/elements/cfpb-select/index.css +2 -0
  79. package/dist/elements/cfpb-select/index.css.map +7 -0
  80. package/dist/elements/cfpb-select/index.js +42 -0
  81. package/dist/elements/cfpb-select/index.js.map +7 -0
  82. package/dist/elements/cfpb-select-list/index.js +39 -0
  83. package/dist/elements/cfpb-select-list/index.js.map +7 -0
  84. package/dist/elements/cfpb-tag-filter/index.js +3 -3
  85. package/dist/elements/cfpb-tag-filter/index.js.map +3 -3
  86. package/dist/elements/cfpb-tag-group/index.js +3 -3
  87. package/dist/elements/cfpb-tag-group/index.js.map +4 -4
  88. package/dist/elements/cfpb-tag-topic/index.js +4 -4
  89. package/dist/elements/cfpb-tag-topic/index.js.map +2 -2
  90. package/dist/elements/index.css +2 -0
  91. package/dist/elements/index.css.map +7 -0
  92. package/dist/elements/index.js +7 -6
  93. package/dist/elements/index.js.map +4 -4
  94. package/dist/index.css +1 -1
  95. package/dist/index.css.map +3 -3
  96. package/dist/index.js +7 -6
  97. package/dist/index.js.map +4 -4
  98. package/dist/utilities/index.css +1 -1
  99. package/dist/utilities/index.css.map +2 -2
  100. package/dist/utilities/index.js +1 -1
  101. package/dist/utilities/index.js.map +4 -4
  102. package/package.json +1 -1
  103. package/src/components/cfpb-buttons/button-group.scss +1 -1
  104. package/src/components/cfpb-buttons/button-link.scss +10 -54
  105. package/src/components/cfpb-buttons/button.scss +3 -3
  106. package/src/components/cfpb-buttons/vars.scss +1 -1
  107. package/src/components/cfpb-expandables/expandable-group.scss +1 -1
  108. package/src/components/cfpb-expandables/expandable.js +3 -0
  109. package/src/components/cfpb-expandables/expandable.scss +1 -1
  110. package/src/components/cfpb-expandables/summary.scss +1 -1
  111. package/src/components/cfpb-forms/form-alert.scss +1 -1
  112. package/src/components/cfpb-forms/form-field.scss +6 -6
  113. package/src/components/cfpb-forms/form.scss +1 -1
  114. package/src/components/cfpb-forms/label.scss +2 -2
  115. package/src/components/cfpb-forms/multiselect.js +1 -1
  116. package/src/components/cfpb-forms/multiselect.scss +1 -1
  117. package/src/components/cfpb-forms/range.scss +7 -7
  118. package/src/components/cfpb-forms/search-input.scss +1 -1
  119. package/src/components/cfpb-forms/select.scss +1 -1
  120. package/src/components/cfpb-forms/tag.scss +1 -1
  121. package/src/components/cfpb-forms/text-input.scss +1 -1
  122. package/src/components/cfpb-icons/icon.scss +1 -1
  123. package/src/components/cfpb-layout/card-group.scss +1 -1
  124. package/src/components/cfpb-layout/card.scss +1 -1
  125. package/src/components/cfpb-layout/email-signup.scss +1 -1
  126. package/src/components/cfpb-layout/featured-content-module.scss +1 -1
  127. package/src/components/cfpb-layout/hero.scss +1 -1
  128. package/src/components/cfpb-layout/layout.scss +9 -9
  129. package/src/components/cfpb-layout/well.scss +1 -1
  130. package/src/components/cfpb-notifications/banner.scss +1 -1
  131. package/src/components/cfpb-notifications/notification.scss +1 -1
  132. package/src/components/cfpb-pagination/pagination.scss +1 -1
  133. package/src/components/cfpb-tables/table.scss +1 -1
  134. package/src/components/cfpb-tooltips/tooltip.scss +1 -1
  135. package/src/components/cfpb-typography/date.scss +1 -1
  136. package/src/components/cfpb-typography/list.scss +1 -1
  137. package/src/components/cfpb-typography/meta-header.scss +1 -1
  138. package/src/components/cfpb-typography/mixins.scss +1 -1
  139. package/src/components/cfpb-typography/pull-quote.scss +1 -1
  140. package/src/components/cfpb-typography/slug-header.scss +1 -1
  141. package/src/components/cfpb-typography/tagline.scss +1 -1
  142. package/src/elements/abstracts/custom-props.css +123 -0
  143. package/src/{abstracts → elements/abstracts}/grid-mixins.scss +2 -1
  144. package/src/{abstracts → elements/abstracts}/heading-mixins.scss +1 -0
  145. package/src/{abstracts → elements/abstracts}/index.scss +1 -0
  146. package/src/{abstracts → elements/abstracts}/media-queries.scss +1 -1
  147. package/src/elements/abstracts/sizing-vars.scss +66 -0
  148. package/src/elements/abstracts/vars.css +79 -0
  149. package/src/{base → elements/base}/base.scss +14 -14
  150. package/src/elements/cfpb-button/cfpb-button-group.scss +12 -0
  151. package/src/elements/cfpb-button/cfpb-button-link.scss +103 -0
  152. package/src/elements/cfpb-button/cfpb-button.component.scss +11 -4
  153. package/src/elements/cfpb-button/cfpb-button.scss +218 -0
  154. package/src/elements/cfpb-button/index.js +44 -30
  155. package/src/elements/cfpb-button/vars.css +30 -0
  156. package/src/elements/cfpb-checkbox-icon/cfpb-checkbox-icon.component.scss +88 -0
  157. package/src/elements/cfpb-checkbox-icon/index.js +104 -0
  158. package/src/elements/cfpb-expandable/cfpb-expandable.component.scss +218 -0
  159. package/src/elements/cfpb-expandable/index.js +127 -0
  160. package/src/elements/cfpb-file-upload/cfpb-file-upload.component.scss +2 -2
  161. package/src/elements/cfpb-file-upload/index.js +25 -27
  162. package/src/elements/cfpb-form-alert/cfpb-form-alert.component.scss +36 -0
  163. package/src/elements/cfpb-form-alert/index.js +55 -0
  164. package/src/elements/cfpb-form-choice/cfpb-form-choice.component.scss +42 -81
  165. package/src/elements/cfpb-form-choice/index.js +58 -18
  166. package/src/elements/cfpb-form-search/cfpb-form-search.component.scss +54 -0
  167. package/src/elements/cfpb-form-search/index.js +194 -0
  168. package/src/elements/cfpb-form-search-input/cfpb-form-search-input.component.scss +217 -0
  169. package/src/elements/cfpb-form-search-input/index.js +140 -0
  170. package/src/elements/cfpb-icon-text/cfpb-icon-text.component.scss +33 -39
  171. package/src/elements/cfpb-icon-text/index.js +32 -104
  172. package/src/elements/cfpb-label/cfpb-label.component.scss +2 -2
  173. package/src/elements/cfpb-label/index.js +6 -9
  174. package/src/elements/cfpb-list/cfpb-list.component.scss +34 -0
  175. package/src/elements/cfpb-list/index.js +379 -0
  176. package/src/elements/cfpb-list/index.spec.js +214 -0
  177. package/src/elements/cfpb-list-item/cfpb-list-item.component.scss +69 -0
  178. package/src/elements/cfpb-list-item/index.js +215 -0
  179. package/src/elements/cfpb-pagination/cfpb-pagination.component.scss +2 -7
  180. package/src/elements/cfpb-pagination/index.js +6 -8
  181. package/src/elements/cfpb-select/cfpb-select.component.scss +241 -0
  182. package/src/elements/cfpb-select/index.js +371 -0
  183. package/src/elements/cfpb-select/multiple-select-event-proxy.js +88 -0
  184. package/src/elements/cfpb-select/single-select-event-proxy.js +47 -0
  185. package/src/elements/cfpb-tag-filter/cfpb-tag-filter.component.scss +6 -3
  186. package/src/elements/cfpb-tag-filter/index.js +15 -7
  187. package/src/elements/cfpb-tag-group/cfpb-tag-group.component.scss +2 -2
  188. package/src/elements/cfpb-tag-group/index.js +53 -6
  189. package/src/elements/cfpb-tag-topic/cfpb-tag-topic.component.scss +2 -2
  190. package/src/elements/cfpb-tag-topic/index.js +5 -7
  191. package/src/elements/cfpb-utilities/parse-child-data.js +50 -0
  192. package/src/elements/cfpb-utilities/parse-child-data.spec.js +56 -0
  193. package/src/elements/cfpb-utilities/search-service.js +46 -0
  194. package/src/elements/cfpb-utilities/search-service.spec.js +138 -0
  195. package/src/elements/cfpb-utilities/transition/transition.scss +98 -0
  196. package/src/elements/index.js +7 -1
  197. package/src/index.js +2 -2
  198. package/src/index.scss +14 -2
  199. package/src/tokens/abstracts/custom-props.json +1642 -0
  200. package/src/tokens/abstracts/vars.json +1319 -0
  201. package/src/tokens/cfpb-button/vars.json +436 -0
  202. package/src/utilities/breakpoint-state.js +1 -1
  203. package/src/utilities/transition/max-height-transition.js +74 -0
  204. package/src/utilities/utilities.scss +1 -1
  205. package/dist/elements/cfpb-checkbox/index.js +0 -29
  206. package/src/abstracts/custom-props.scss +0 -175
  207. package/src/abstracts/vars.scss +0 -184
  208. package/src/elements/cfpb-multiselect/cfpb-multiselect.component.scss +0 -225
  209. package/src/elements/cfpb-multiselect/index.js +0 -444
  210. package/src/elements/cfpb-multiselect/multiselect-model.js +0 -288
  211. package/src/elements/cfpb-multiselect/multiselect-model.spec.js +0 -236
  212. /package/src/{abstracts → elements/abstracts}/index.js +0 -0
  213. /package/src/{abstracts → elements/abstracts}/vars-breakpoints.js +0 -0
  214. /package/src/{abstracts → elements/abstracts}/vars-breakpoints.scss +0 -0
  215. /package/src/{base → elements/base}/font.scss +0 -0
  216. /package/src/{base → elements/base}/index.js +0 -0
  217. /package/src/{base → elements/base}/index.scss +0 -0
  218. /package/src/{base → elements/base}/normalize.scss +0 -0
@@ -1,288 +0,0 @@
1
- /**
2
- *
3
- * @element cfpb-multiselect.
4
- * @slot - The main content for the upload button.
5
- */
6
- export class MultiselectModel extends EventTarget {
7
- // Declare private properties.
8
- #options;
9
- #name;
10
- #max;
11
- #optionsData;
12
- #selectedIndices;
13
- #filterIndicesList;
14
- #lastFilterIndicesList;
15
- #index;
16
-
17
- // Undefined return value for void methods.
18
- #UNDEFINED;
19
-
20
- /**
21
- * @class
22
- * MultiselectModel
23
- * @param {HTMLOptionsCollection} options
24
- * Set of options from a <select> element.
25
- * @param {string} name - a unique name for this multiselect.
26
- * @param {object} config - Customization of Multiselect behavior
27
- */
28
- constructor(options, name, config) {
29
- super();
30
-
31
- this.#options = options;
32
- this.#name = name;
33
- this.#max = config?.maxSelections || MultiselectModel.MAX_SELECTIONS;
34
- this.#optionsData = [];
35
-
36
- this.#selectedIndices = [];
37
- this.#filterIndicesList = [];
38
-
39
- /* When the options list is filtered, we store a list of filtered indices
40
- so that when the filter changes we can reset the last matched options. */
41
- this.#lastFilterIndicesList = [];
42
-
43
- // Which option is in focus. -1 means the focus is on the search input.
44
- this.#index = -1;
45
- }
46
-
47
- /**
48
- * @param {HTMLElement} item - An option HTML node.
49
- * @returns {string} A (hopefully) unique ID.
50
- * If it's not unique, we have a duplicate option value.
51
- */
52
- #getOptionId(item) {
53
- return (
54
- this.#name + '-' + item.value.trim().replace(/\s+/g, '-').toLowerCase()
55
- );
56
- }
57
-
58
- /**
59
- * @returns {boolean}
60
- * True if the maximum number of options are checked, false otherwise.
61
- */
62
- isAtMaxSelections() {
63
- return this.#selectedIndices.length >= this.#max;
64
- }
65
-
66
- /**
67
- * Cleans up a list of options for saving to memory.
68
- * @param {HTMLOptionsCollection} list - The options from a select element.
69
- * @returns {Array} An array of option objects.
70
- */
71
- #formatOptions(list) {
72
- let item;
73
- const cleaned = [];
74
-
75
- let isChecked = false;
76
- let isSelected = false;
77
- for (let i = 0, len = list.length; i < len; i++) {
78
- item = list[i];
79
- isSelected = item.defaultSelected ? item.defaultSelected : false;
80
- isChecked = this.isAtMaxSelections() ? false : isSelected;
81
- cleaned.push({
82
- id: this.#getOptionId(item),
83
- value: item.value,
84
- label: item.text,
85
- text: item.text,
86
- checked: isChecked,
87
- index: i,
88
- });
89
-
90
- // If an option is initially checked, we need to record it.
91
- if (isChecked) {
92
- this.#selectedIndices.push(i);
93
- }
94
- }
95
-
96
- return cleaned;
97
- }
98
-
99
- /**
100
- * @returns {MultiselectModel} An instance.
101
- */
102
- init() {
103
- this.#optionsData = this.#formatOptions(this.#options);
104
-
105
- return this;
106
- }
107
-
108
- /**
109
- * Toggle checked value of an option.
110
- * @param {number} index - The index position of the option in the list.
111
- * @returns {boolean} A value of true is checked and false is unchecked.
112
- */
113
- toggleOption(index) {
114
- const isChecked = !this.#optionsData[index].checked;
115
-
116
- if (isChecked && this.#selectedIndices.length < this.#max) {
117
- this.#optionsData[index].checked = true;
118
- this.#selectedIndices.push(index);
119
- this.#selectedIndices.sort();
120
-
121
- return true;
122
- }
123
-
124
- // We're over the max selections, reverse the check of the option.
125
- this.#optionsData[index].checked = false;
126
- this.#selectedIndices = this.#selectedIndices.filter(function (currIndex) {
127
- return currIndex !== index;
128
- });
129
-
130
- return false;
131
- }
132
-
133
- /**
134
- * Utility function for Array.reduce() used in searchIndices.
135
- * @param {Array} aggregate - The reducer's accumulator.
136
- * @param {object} item - Each item in the collection.
137
- * @param {number} index - The index of item in the collection.
138
- * @param {string} value - The value of item in the collection.
139
- * @returns {Array} The reducer's accumulator.
140
- */
141
- #searchAggregator(aggregate, item, index, value) {
142
- if (MultiselectModel.stringMatch(item.text, value)) {
143
- aggregate.push(index);
144
- }
145
- return aggregate;
146
- }
147
-
148
- /**
149
- * Search for a query string in the options text and return the indices of
150
- * the matching positions in the options array.
151
- * @param {string} query - A query string.
152
- * @returns {Array} List of indices of the matching entries from the options.
153
- */
154
- filterIndices(query) {
155
- // Convert query to a string if it's not.
156
- if (Object.prototype.toString.call(query) !== '[object String]') {
157
- query = '';
158
- }
159
-
160
- this.#lastFilterIndicesList = this.#filterIndicesList;
161
-
162
- if (this.#optionsData.length > 0) {
163
- this.#filterIndicesList = this.#optionsData.reduce((acc, item, index) => {
164
- return this.#searchAggregator(acc, item, index, query);
165
- }, []);
166
- }
167
-
168
- // Reset index position.
169
- this.#index = -1;
170
-
171
- return this.#filterIndicesList;
172
- }
173
-
174
- // This is used to search the items in the collection.
175
- clearFilter() {
176
- this.#filterIndicesList = this.#lastFilterIndicesList = [];
177
- return this.#UNDEFINED;
178
- }
179
-
180
- get filterIndicesList() {
181
- return this.#filterIndicesList;
182
- }
183
-
184
- get lastFilterIndicesList() {
185
- return this.#lastFilterIndicesList;
186
- }
187
-
188
- // This is used to check an item in the collection.
189
- get selectedIndices() {
190
- return this.#selectedIndices;
191
- }
192
-
193
- /**
194
- * Retrieve an option object from the options list.
195
- * @param {number} index - The index position in the options list.
196
- * @returns {object} The option object with text, value, and checked value.
197
- */
198
- getOption(index) {
199
- return this.#optionsData[index];
200
- }
201
-
202
- /**
203
- * Set the index of the collection (represents the highlighted option).
204
- * @param {number} value - The index to set.
205
- */
206
- set index(value) {
207
- const filterCount = this.#filterIndicesList.length;
208
- const count = filterCount === 0 ? this.#optionsData.length : filterCount;
209
- if (value < 0) {
210
- this.#index = -1;
211
- } else if (value >= count) {
212
- this.#index = count - 1;
213
- } else {
214
- this.#index = value;
215
- }
216
- }
217
-
218
- /**
219
- * @returns {number} The current index (highlighted option).
220
- */
221
- get index() {
222
- return this.#index;
223
- }
224
-
225
- resetIndex() {
226
- this.#index = -1;
227
- return this.#index;
228
- }
229
-
230
- get options() {
231
- return this.#optionsData;
232
- }
233
-
234
- // These are used to highlight items in the collection.
235
-
236
- /*
237
-
238
- get items() {
239
- console.log([...this.#items]);
240
- return [...this.#items];
241
- }
242
-
243
- set items(newItems) {
244
- this.#items = newItems;
245
- this.#notify();
246
- }
247
-
248
- addItem(item) {
249
- this.#items.push(item);
250
- this.#notify();
251
- }
252
-
253
- removeItem(indexToRemove) {
254
- this.#items.splice(indexToRemove, 1);
255
- }
256
-
257
- #notify() {
258
- this.dispatchEvent(new Event('change'));
259
- }
260
-
261
- subscribe(callback) {
262
- this.addEventListener('change', callback);
263
- return () => this.removeEventListener('change', callback);
264
- }
265
- */
266
-
267
- // How many options may be checked.
268
- static MAX_SELECTIONS = 5;
269
-
270
- /**
271
- * Escapes a string.
272
- * @param {string} str - The string to escape.
273
- * @returns {string} The escaped string.
274
- */
275
- static stringEscape(str) {
276
- return str.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
277
- }
278
-
279
- /**
280
- * Tests whether a string matches another.
281
- * @param {string} x - The control string.
282
- * @param {string} y - The comparison string.
283
- * @returns {boolean} True if `x` and `y` match, false otherwise.
284
- */
285
- static stringMatch(x, y) {
286
- return RegExp(MultiselectModel.stringEscape(y.trim()), 'i').test(x);
287
- }
288
- }
@@ -1,236 +0,0 @@
1
- import { MultiselectModel } from './multiselect-model.js';
2
-
3
- const HTML_SNIPPET = `
4
- <select class="o-multiselect" multiple>
5
- <option value="mortgages">
6
- Mortgages
7
- </option>
8
- <option value="financial-education" selected>
9
- Financial education
10
- </option>
11
- <option value="financial-well-being">
12
- Financial well-being
13
- </option>
14
- <option value="student-loans">
15
- Student loans
16
- </option>
17
- <option value="rulemaking">
18
- Rulemaking
19
- </option>
20
- <option value="banking">
21
- Banking
22
- </option>
23
- </select>
24
- `;
25
-
26
- let multiselectModel;
27
- let selectDom;
28
-
29
- describe('MultiselectModel', () => {
30
- beforeEach(() => {
31
- document.body.innerHTML = HTML_SNIPPET;
32
-
33
- selectDom = document.querySelector('select[multiple]');
34
- multiselectModel = new MultiselectModel(selectDom.options).init();
35
- });
36
-
37
- describe('init()', () => {
38
- it('should correctly initialize when given valid options', () => {
39
- multiselectModel = new MultiselectModel(selectDom.options).init();
40
- expect(multiselectModel.constructor).toBe(MultiselectModel);
41
- });
42
- });
43
-
44
- describe('toggleOption()', () => {
45
- it('should toggle checked value of option', () => {
46
- expect(multiselectModel.getOption(0).checked).toBe(false);
47
- expect(multiselectModel.toggleOption(0)).toBe(true);
48
- expect(multiselectModel.getOption(0).checked).toBe(true);
49
-
50
- expect(multiselectModel.getOption(1).checked).toBe(true);
51
- expect(multiselectModel.toggleOption(1)).toBe(false);
52
- expect(multiselectModel.getOption(1).checked).toBe(false);
53
-
54
- expect(multiselectModel.getOption(2).checked).toBe(false);
55
- expect(multiselectModel.toggleOption(2)).toBe(true);
56
- expect(multiselectModel.getOption(2).checked).toBe(true);
57
-
58
- expect(multiselectModel.getOption(3).checked).toBe(false);
59
- expect(multiselectModel.toggleOption(3)).toBe(true);
60
- expect(multiselectModel.getOption(3).checked).toBe(true);
61
-
62
- expect(multiselectModel.getOption(4).checked).toBe(false);
63
- expect(multiselectModel.toggleOption(4)).toBe(true);
64
- expect(multiselectModel.getOption(4).checked).toBe(true);
65
-
66
- expect(multiselectModel.getOption(5).checked).toBe(false);
67
- expect(multiselectModel.toggleOption(5)).toBe(true);
68
- expect(multiselectModel.getOption(5).checked).toBe(true);
69
-
70
- // Try to push beyond maximum selections.
71
- expect(multiselectModel.toggleOption(1)).toBe(false);
72
- expect(multiselectModel.getOption(1).checked).toBe(false);
73
- expect(multiselectModel.toggleOption(2)).toBe(false);
74
- expect(multiselectModel.getOption(2).checked).toBe(false);
75
- expect(multiselectModel.toggleOption(1)).toBe(true);
76
- expect(multiselectModel.getOption(1).checked).toBe(true);
77
- });
78
- });
79
-
80
- describe('getSelectedIndices()', () => {
81
- it('should get the indices of the checked options', () => {
82
- expect(multiselectModel.selectedIndices[0]).toBe(1);
83
- multiselectModel.toggleOption(0);
84
- expect(multiselectModel.selectedIndices[0]).toBe(0);
85
- expect(multiselectModel.selectedIndices[1]).toBe(1);
86
- });
87
- });
88
-
89
- describe('isAtMaxSelections()', () => {
90
- it('should toggle checked value of option', () => {
91
- expect(multiselectModel.isAtMaxSelections()).toBe(false);
92
-
93
- multiselectModel.toggleOption(0);
94
- expect(multiselectModel.isAtMaxSelections()).toBe(false);
95
-
96
- // No need to toggle the second option because it's already checked.
97
-
98
- multiselectModel.toggleOption(2);
99
- expect(multiselectModel.isAtMaxSelections()).toBe(false);
100
-
101
- multiselectModel.toggleOption(3);
102
- expect(multiselectModel.isAtMaxSelections()).toBe(false);
103
-
104
- multiselectModel.toggleOption(4);
105
- expect(multiselectModel.isAtMaxSelections()).toBe(true);
106
-
107
- multiselectModel.toggleOption(5);
108
- expect(multiselectModel.isAtMaxSelections()).toBe(true);
109
-
110
- multiselectModel.toggleOption(5);
111
- expect(multiselectModel.isAtMaxSelections()).toBe(true);
112
-
113
- expect(multiselectModel.toggleOption(4)).toBe(false);
114
- expect(multiselectModel.isAtMaxSelections()).toBe(false);
115
- });
116
- });
117
-
118
- describe('filterIndices()', () => {
119
- it('should return indices of matched options in a search', () => {
120
- expect(multiselectModel.filterIndices('mo').length).toBe(1);
121
- expect(multiselectModel.filterIndices('mort').length).toBe(1);
122
- expect(multiselectModel.filterIndices('mort')[0]).toBe(0);
123
- expect(multiselectModel.filterIndices('fin').length).toBe(2);
124
- expect(multiselectModel.filterIndices('fin')[0]).toBe(1);
125
- expect(multiselectModel.filterIndices('fin')[1]).toBe(2);
126
- expect(multiselectModel.filterIndices('being').length).toBe(1);
127
- expect(multiselectModel.filterIndices('being')[0]).toBe(2);
128
- expect(multiselectModel.filterIndices('').length).toBe(6);
129
- expect(multiselectModel.filterIndices().length).toBe(6);
130
- expect(multiselectModel.filterIndices([]).length).toBe(6);
131
- expect(multiselectModel.filterIndices({}).length).toBe(6);
132
- });
133
- });
134
-
135
- describe('clearFilter()', () => {
136
- it('should clear current and last matched options in a search', () => {
137
- multiselectModel.filterIndices('fin');
138
- expect(multiselectModel.lastFilterIndicesList.length).toBe(0);
139
- expect(multiselectModel.filterIndicesList.length).toBe(2);
140
- multiselectModel.filterIndices('mo');
141
- expect(multiselectModel.lastFilterIndicesList.length).toBe(2);
142
- expect(multiselectModel.filterIndicesList.length).toBe(1);
143
- multiselectModel.clearFilter();
144
- expect(multiselectModel.lastFilterIndicesList.length).toBe(0);
145
- expect(multiselectModel.filterIndicesList.length).toBe(0);
146
- });
147
- });
148
-
149
- describe('getFilterIndices()', () => {
150
- it('should return current indices of matched options in a search', () => {
151
- expect(multiselectModel.filterIndicesList.length).toBe(0);
152
- multiselectModel.filterIndices('fin');
153
- expect(multiselectModel.filterIndicesList.length).toBe(2);
154
- expect(multiselectModel.filterIndicesList[0]).toBe(1);
155
- expect(multiselectModel.filterIndicesList[1]).toBe(2);
156
- });
157
- });
158
-
159
- describe('getLastFilterIndices()', () => {
160
- it('should return indices of the last matched options in a search', () => {
161
- expect(multiselectModel.lastFilterIndicesList.length).toBe(0);
162
- multiselectModel.filterIndices('fin');
163
- expect(multiselectModel.lastFilterIndicesList.length).toBe(0);
164
- multiselectModel.filterIndices('mo');
165
- expect(multiselectModel.lastFilterIndicesList.length).toBe(2);
166
- expect(multiselectModel.lastFilterIndicesList[0]).toBe(1);
167
- expect(multiselectModel.lastFilterIndicesList[1]).toBe(2);
168
- multiselectModel.filterIndices('being');
169
- expect(multiselectModel.lastFilterIndicesList.length).toBe(1);
170
- expect(multiselectModel.lastFilterIndicesList[0]).toBe(0);
171
- });
172
- });
173
-
174
- describe('getIndex()', () => {
175
- it('should get correct index when no filter results', () => {
176
- expect(multiselectModel.index).toBe(-1);
177
- multiselectModel.index = 2;
178
- expect(multiselectModel.index).toBe(2);
179
- multiselectModel.filterIndices('asdf');
180
- expect(multiselectModel.index).toBe(-1);
181
- });
182
-
183
- it('should get reset index when options are filtered', () => {
184
- expect(multiselectModel.index).toBe(-1);
185
- multiselectModel.index = 2;
186
- expect(multiselectModel.index).toBe(2);
187
- multiselectModel.filterIndices('mo');
188
- expect(multiselectModel.index).toBe(-1);
189
- });
190
- });
191
-
192
- describe('setIndex()', () => {
193
- it('should set index within available option range', () => {
194
- expect(multiselectModel.index).toBe(-1);
195
- multiselectModel.index = 0;
196
- expect(multiselectModel.index).toBe(0);
197
- multiselectModel.index = 1;
198
- expect(multiselectModel.index).toBe(1);
199
- multiselectModel.index = 2;
200
- expect(multiselectModel.index).toBe(2);
201
- multiselectModel.index = 10;
202
- expect(multiselectModel.index).toBe(5);
203
- multiselectModel.index = -2;
204
- expect(multiselectModel.index).toBe(-1);
205
- });
206
-
207
- it('should set index within filtered option range', () => {
208
- expect(multiselectModel.index).toBe(-1);
209
- multiselectModel.filterIndices('fin');
210
- multiselectModel.index = 0;
211
- expect(multiselectModel.index).toBe(0);
212
- expect(multiselectModel.filterIndicesList[multiselectModel.index]).toBe(
213
- 1,
214
- );
215
- multiselectModel.index = 1;
216
- expect(multiselectModel.index).toBe(1);
217
- multiselectModel.index = 2;
218
- expect(multiselectModel.index).toBe(1);
219
- });
220
- });
221
-
222
- describe('resetIndex()', () => {
223
- it('should return -1 for index when called', () => {
224
- expect(multiselectModel.resetIndex()).toBe(-1);
225
- });
226
- });
227
-
228
- describe('getOption()', () => {
229
- it('should return the correct option when requested', () => {
230
- expect(multiselectModel.getOption(2).text).toBe('Financial well-being');
231
- expect(multiselectModel.getOption(2).value).toBe('financial-well-being');
232
- expect(multiselectModel.getOption(2).checked).toBe(false);
233
- expect(multiselectModel.getOption(1).checked).toBe(true);
234
- });
235
- });
236
- });
File without changes
File without changes
File without changes
File without changes
File without changes