@qld-gov-au/qgds-bootstrap5 1.1.40 → 2.0.0

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 (184) hide show
  1. package/.eslintrc.cjs +27 -27
  2. package/.vscode/settings.json +5 -5
  3. package/dist/assets/components/bs5/button/button.hbs +48 -30
  4. package/dist/assets/components/bs5/card/card.hbs +3 -17
  5. package/dist/assets/components/bs5/containerLayout/containerLayout.hbs +100 -0
  6. package/dist/assets/components/bs5/footer/customLinks.hbs +7 -0
  7. package/dist/assets/components/bs5/footer/feedbackForm.hbs +25 -0
  8. package/dist/assets/components/bs5/footer/followLinks.hbs +14 -0
  9. package/dist/assets/components/bs5/footer/footer.hbs +229 -346
  10. package/dist/assets/components/bs5/formcheck/formcheck.hbs +1 -1
  11. package/dist/assets/components/bs5/head/head.hbs +4 -4
  12. package/dist/assets/components/bs5/header/header.hbs +124 -878
  13. package/dist/assets/components/bs5/header/headerBrand.hbs +35 -0
  14. package/dist/assets/components/bs5/link/link.hbs +41 -0
  15. package/dist/assets/components/bs5/logo/logoCOALandscape.hbs +110 -55
  16. package/dist/assets/components/bs5/logo/logoCOALandscape2Lines.hbs +2 -1
  17. package/dist/assets/components/bs5/navbar/navbar.hbs +65 -245
  18. package/dist/assets/components/bs5/pageLayout/templates/contentPageWithForm.hbs +53 -22
  19. package/dist/assets/components/bs5/pageLayout/templates/contentPageWithSideNavigation.hbs +79 -59
  20. package/dist/assets/components/bs5/pageLayout/templates/homePage.hbs +111 -0
  21. package/dist/assets/components/bs5/searchInput/searchInput.hbs +9 -11
  22. package/dist/assets/css/qld.bootstrap.css +1 -1
  23. package/dist/assets/css/qld.bootstrap.css.map +3 -3
  24. package/dist/assets/js/bootstrap.bundle.js +3 -6
  25. package/dist/assets/js/bootstrap.bundle.js.map +1 -1
  26. package/dist/assets/js/bootstrap.bundle.min.js +2 -2
  27. package/dist/assets/js/bootstrap.bundle.min.js.map +1 -1
  28. package/dist/assets/js/bootstrap.js +3 -6
  29. package/dist/assets/js/bootstrap.min.js +2 -2
  30. package/dist/assets/js/bootstrap.min.js.map +1 -1
  31. package/dist/assets/js/handlebars.helpers.bundle.js.map +2 -2
  32. package/dist/assets/js/handlebars.helpers.js +34 -34
  33. package/dist/assets/js/handlebars.init.min.js +1055 -2041
  34. package/dist/assets/js/handlebars.init.min.js.map +4 -4
  35. package/dist/assets/js/handlebars.partials.js +14 -6
  36. package/dist/assets/js/qld.bootstrap.min.js +9 -9
  37. package/dist/assets/js/qld.bootstrap.min.js.map +4 -4
  38. package/dist/assets/node/handlebars.init.min.js +538 -108
  39. package/dist/assets/node/handlebars.init.min.js.map +3 -3
  40. package/dist/components/bs5/button/button.hbs +48 -30
  41. package/dist/components/bs5/card/card.hbs +3 -17
  42. package/dist/components/bs5/containerLayout/containerLayout.hbs +100 -0
  43. package/dist/components/bs5/footer/customLinks.hbs +7 -0
  44. package/dist/components/bs5/footer/feedbackForm.hbs +25 -0
  45. package/dist/components/bs5/footer/followLinks.hbs +14 -0
  46. package/dist/components/bs5/footer/footer.hbs +229 -346
  47. package/dist/components/bs5/formcheck/formcheck.hbs +1 -1
  48. package/dist/components/bs5/head/head.hbs +4 -4
  49. package/dist/components/bs5/header/header.hbs +124 -878
  50. package/dist/components/bs5/header/headerBrand.hbs +35 -0
  51. package/dist/components/bs5/link/link.hbs +41 -0
  52. package/dist/components/bs5/logo/logoCOALandscape.hbs +110 -55
  53. package/dist/components/bs5/logo/logoCOALandscape2Lines.hbs +2 -1
  54. package/dist/components/bs5/navbar/navbar.hbs +65 -245
  55. package/dist/components/bs5/pageLayout/templates/contentPageWithForm.hbs +53 -22
  56. package/dist/components/bs5/pageLayout/templates/contentPageWithSideNavigation.hbs +79 -59
  57. package/dist/components/bs5/pageLayout/templates/homePage.hbs +111 -0
  58. package/dist/components/bs5/searchInput/searchInput.hbs +9 -11
  59. package/dist/components/handlebars.helpers.js +34 -34
  60. package/dist/components/handlebars.partials.js +14 -6
  61. package/dist/package.json +2 -2
  62. package/dist/sample-data/button/button.data.json +10 -8
  63. package/dist/sample-data/footer/footer.data.json +128 -84
  64. package/dist/sample-data/formcheck/stories/checkbox/checkbox.data.json +51 -46
  65. package/dist/sample-data/formcheck/stories/radio/radio.data.json +51 -46
  66. package/dist/sample-data/header/header.variant.coBrand.data.json +28 -40
  67. package/dist/sample-data/header/header.variant.endorsed.data.json +116 -150
  68. package/dist/sample-data/header/header.variant.masterBrand.data.json +116 -152
  69. package/dist/sample-data/header/header.variant.standAlone.data.json +118 -150
  70. package/dist/sample-data/header/header.variant.subBrand.data.json +32 -159
  71. package/dist/sample-data/inpageAlert/inpageAlert.data.json +6 -6
  72. package/dist/sample-data/link/link.data.json +77 -0
  73. package/dist/sample-data/logo/logo.data.json +1 -0
  74. package/dist/sample-data/navbar/navbar.data.json +191 -0
  75. package/dist/sample-data/searchInput/searchInput.data.json +2 -3
  76. package/dist/sample-data/tabs/tabs.data.json +45 -44
  77. package/package.json +2 -2
  78. package/src/components/bs5/accordion/Accordion.mdx +8 -2
  79. package/src/components/bs5/banner/Banner.mdx +6 -1
  80. package/src/components/bs5/banner/banner.scss +16 -9
  81. package/src/components/bs5/banner/banner.stories.js +17 -17
  82. package/src/components/bs5/breadcrumbs/Breadcrumbs.mdx +8 -2
  83. package/src/components/bs5/breadcrumbs/breadcrumbs.functions.js +2 -0
  84. package/src/components/bs5/breadcrumbs/breadcrumbs.scss +1 -1
  85. package/src/components/bs5/button/button.data.json +10 -8
  86. package/src/components/bs5/button/button.hbs +48 -30
  87. package/src/components/bs5/button/button.scss +61 -0
  88. package/src/components/bs5/button/button.stories.js +29 -10
  89. package/src/components/bs5/callToAction/callToAction.mdx +8 -3
  90. package/src/components/bs5/card/Card.mdx +8 -2
  91. package/src/components/bs5/card/card.hbs +3 -17
  92. package/src/components/bs5/card/card.scss +103 -103
  93. package/src/components/bs5/containerLayout/containerLayout.hbs +100 -0
  94. package/src/components/bs5/containerLayout/containerLayout.stories.js +83 -0
  95. package/src/components/bs5/footer/Footer.js +3 -3
  96. package/src/components/bs5/footer/Footer.mdx +8 -2
  97. package/src/components/bs5/footer/customLinks.hbs +7 -0
  98. package/src/components/bs5/footer/feedbackForm.hbs +25 -0
  99. package/src/components/bs5/footer/followLinks.hbs +14 -0
  100. package/src/components/bs5/footer/footer.data.json +128 -84
  101. package/src/components/bs5/footer/footer.functions.js +2 -1
  102. package/src/components/bs5/footer/footer.hbs +229 -346
  103. package/src/components/bs5/footer/footer.scss +262 -272
  104. package/src/components/bs5/footer/footer.stories.js +4 -92
  105. package/src/components/bs5/footer/footer_formio.scss +219 -0
  106. package/src/components/bs5/formcheck/formcheck.hbs +1 -1
  107. package/src/components/bs5/formcheck/formcheck.scss +161 -139
  108. package/src/components/bs5/formcheck/stories/checkbox/checkbox.data.json +51 -46
  109. package/src/components/bs5/formcheck/stories/radio/radio.data.json +51 -46
  110. package/src/components/bs5/globalAlert/GlobalAlert.mdx +8 -2
  111. package/src/components/bs5/globalAlert/globalAlert.test.js +3 -11
  112. package/src/components/bs5/header/_header-variables.scss +272 -0
  113. package/src/components/bs5/header/header.functions.js +9 -9
  114. package/src/components/bs5/header/header.hbs +124 -878
  115. package/src/components/bs5/header/header.scss +279 -411
  116. package/src/components/bs5/header/header.stories.js +8 -28
  117. package/src/components/bs5/header/header.variant.coBrand.data.json +28 -40
  118. package/src/components/bs5/header/header.variant.endorsed.data.json +116 -150
  119. package/src/components/bs5/header/header.variant.masterBrand.data.json +116 -152
  120. package/src/components/bs5/header/header.variant.standAlone.data.json +118 -150
  121. package/src/components/bs5/header/header.variant.subBrand.data.json +32 -159
  122. package/src/components/bs5/header/headerBrand.hbs +35 -0
  123. package/src/components/bs5/icons/icons.scss +79 -72
  124. package/src/components/bs5/inpageAlert/InpageAlert.mdx +8 -2
  125. package/src/components/bs5/inpageAlert/inpageAlert.data.json +6 -6
  126. package/src/components/bs5/inpagenav/inpagenav.scss +37 -37
  127. package/src/components/bs5/link/link.data.json +77 -0
  128. package/src/components/bs5/link/link.hbs +41 -0
  129. package/src/components/bs5/{pageLayout/pageLayout.js → link/link.js} +4 -5
  130. package/src/components/bs5/link/link.mdx +16 -0
  131. package/src/components/bs5/link/link.scss +81 -0
  132. package/src/components/bs5/link/link.stories.js +126 -0
  133. package/src/components/bs5/linkColumns/linkColumns.mdx +8 -3
  134. package/src/components/bs5/logo/logo.data.json +1 -0
  135. package/src/components/bs5/logo/logoCOALandscape.hbs +110 -55
  136. package/src/components/bs5/logo/logoCOALandscape2Lines.hbs +2 -1
  137. package/src/components/bs5/navbar/Navbar.js +2 -9
  138. package/src/components/bs5/navbar/navbar.data.json +191 -0
  139. package/src/components/bs5/navbar/navbar.functions.js +48 -196
  140. package/src/components/bs5/navbar/navbar.hbs +65 -245
  141. package/src/components/bs5/navbar/navbar.scss +684 -562
  142. package/src/components/bs5/navbar/navbar.stories.js +533 -0
  143. package/src/components/bs5/pageLayout/{FullWidthLandingPage.js → HomePage.js} +2 -2
  144. package/src/components/bs5/pageLayout/pageLayout.stories.js +242 -98
  145. package/src/components/bs5/pageLayout/templates/contentPageWithForm.hbs +53 -22
  146. package/src/components/bs5/pageLayout/templates/contentPageWithSideNavigation.hbs +79 -59
  147. package/src/components/bs5/pageLayout/templates/homePage.hbs +111 -0
  148. package/src/components/bs5/promotionalPanel/PromotionalPanel.mdx +8 -3
  149. package/src/components/bs5/searchInput/__snapshots__/searchInput.test.js.snap +10 -9
  150. package/src/components/bs5/searchInput/search.functions.js +94 -63
  151. package/src/components/bs5/searchInput/searchInput.data.json +2 -3
  152. package/src/components/bs5/searchInput/searchInput.hbs +9 -11
  153. package/src/components/bs5/searchInput/searchInput.scss +297 -255
  154. package/src/components/bs5/searchInput/searchInput.test.js +98 -90
  155. package/src/components/bs5/tabs/tabs.data.json +45 -44
  156. package/src/components/bs5/tabs/tabs.scss +544 -500
  157. package/src/components/bs5/tabs/tabs.stories.js +81 -51
  158. package/src/components/common/layout/container.scss +22 -0
  159. package/src/components/common/layout/content.scss +11 -4
  160. package/src/components/common/layout/grid.scss +26 -0
  161. package/src/css/main.scss +7 -2
  162. package/src/css/mixins/_index.scss +2 -1
  163. package/src/css/mixins/register-vars.scss +23 -0
  164. package/src/css/qld-variables.scss +106 -83
  165. package/src/css/utilities/_index.scss +1 -0
  166. package/src/css/utilities/responsive-visually-hidden.scss +10 -0
  167. package/src/js/handlebars.helpers.js +34 -34
  168. package/src/js/handlebars.partials.js +14 -6
  169. package/src/js/qld.bootstrap.js +10 -11
  170. package/dist/assets/components/bs5/footer/footerForgov.hbs +0 -279
  171. package/dist/assets/components/bs5/pageLayout/pageLayout.hbs +0 -34
  172. package/dist/assets/components/bs5/pageLayout/templates/fullWidthLandingPage.hbs +0 -61
  173. package/dist/components/bs5/footer/footerForgov.hbs +0 -279
  174. package/dist/components/bs5/pageLayout/pageLayout.hbs +0 -34
  175. package/dist/components/bs5/pageLayout/templates/fullWidthLandingPage.hbs +0 -61
  176. package/src/components/bs5/footer/_colours.scss +0 -149
  177. package/src/components/bs5/footer/_measurements.scss +0 -32
  178. package/src/components/bs5/footer/footerForgov.hbs +0 -279
  179. package/src/components/bs5/header/_colours.scss +0 -271
  180. package/src/components/bs5/header/_icons.scss +0 -10
  181. package/src/components/bs5/navbar/_colours.scss +0 -85
  182. package/src/components/bs5/navbar/_icons.scss +0 -64
  183. package/src/components/bs5/pageLayout/pageLayout.hbs +0 -34
  184. package/src/components/bs5/pageLayout/templates/fullWidthLandingPage.hbs +0 -61
@@ -43,7 +43,6 @@ describe("SearchInput", () => {
43
43
  <html>
44
44
  <head>
45
45
  <meta charset="utf-8">
46
- <link rel="stylesheet" href="${__dirname}/../../../../dist/assets/css/qld.bootstrap.css">
47
46
  </head>
48
47
  <body>
49
48
  <form class="site-search" action="https://example.com/search">
@@ -73,7 +72,7 @@ describe("SearchInput", () => {
73
72
 
74
73
  // Ensure elements exist
75
74
  if (!form || !searchInput || !suggestions) {
76
- throw new Error('Required elements not found in DOM');
75
+ throw new Error("Required elements not found in DOM");
77
76
  }
78
77
  });
79
78
 
@@ -84,7 +83,6 @@ describe("SearchInput", () => {
84
83
 
85
84
  test("Search input element and Suggestions container exists and has correct attributes", () => {
86
85
  expect(searchInput).toBeTruthy();
87
- expect(searchInput.getAttribute("placeholder")).toBe(mockData.placeholder);
88
86
  expect(searchInput.getAttribute("id")).toBe(mockData.inputID);
89
87
  expect(searchInput.getAttribute("name").trim()).toBe(mockData.inputName);
90
88
  expect(suggestions).toBeTruthy();
@@ -94,28 +92,32 @@ describe("SearchInput", () => {
94
92
  test("Focus event shows suggestions", async () => {
95
93
  // Initially suggestions are hidden
96
94
  expect(isElementVisible(suggestions)).toBe(false);
97
-
95
+
98
96
  // Ensure input is empty to trigger default suggestions display
99
97
  searchInput.value = "";
100
-
98
+
101
99
  // Instead of relying on event dispatching, directly call the showSuggestions function
102
100
  // that should be available in the window scope after bootstrap loads
103
101
  if (window.showSuggestions || dom.window.showSuggestions) {
104
- await (window.showSuggestions || dom.window.showSuggestions)("", true, form);
102
+ await (window.showSuggestions || dom.window.showSuggestions)(
103
+ "",
104
+ true,
105
+ form,
106
+ );
105
107
  } else {
106
108
  // If showSuggestions is not available globally, manually show suggestions
107
109
  // as the focus event handler would do
108
- const defaultSuggestions = form.querySelector('.default-suggestions');
109
- const dynamicSuggestions = form.querySelector('.dynamic-suggestions');
110
-
110
+ const defaultSuggestions = form.querySelector(".default-suggestions");
111
+ const dynamicSuggestions = form.querySelector(".dynamic-suggestions");
112
+
111
113
  if (defaultSuggestions) {
112
- defaultSuggestions.classList.remove('d-none');
114
+ defaultSuggestions.classList.remove("d-none");
113
115
  }
114
116
  if (dynamicSuggestions) {
115
- dynamicSuggestions.innerHTML = '';
116
- dynamicSuggestions.classList.add('d-none');
117
+ dynamicSuggestions.innerHTML = "";
118
+ dynamicSuggestions.classList.add("d-none");
117
119
  }
118
- suggestions.classList.remove('d-none');
120
+ suggestions.classList.remove("d-none");
119
121
  }
120
122
 
121
123
  // Wait for any asynchronous operations
@@ -131,18 +133,18 @@ describe("SearchInput", () => {
131
133
 
132
134
  // Initially suggestions should be hidden using the d-none class
133
135
 
134
- // Directly simulate the focus event behavior
135
- const defaultSuggestions = form.querySelector('.default-suggestions');
136
- const dynamicSuggestions = form.querySelector('.dynamic-suggestions');
137
-
136
+ // Directly simulate the focus event behavior
137
+ const defaultSuggestions = form.querySelector(".default-suggestions");
138
+ const dynamicSuggestions = form.querySelector(".dynamic-suggestions");
139
+
138
140
  if (defaultSuggestions) {
139
- defaultSuggestions.classList.remove('d-none');
141
+ defaultSuggestions.classList.remove("d-none");
140
142
  }
141
143
  if (dynamicSuggestions) {
142
- dynamicSuggestions.innerHTML = '';
143
- dynamicSuggestions.classList.add('d-none');
144
+ dynamicSuggestions.innerHTML = "";
145
+ dynamicSuggestions.classList.add("d-none");
144
146
  }
145
- suggestions.classList.remove('d-none');
147
+ suggestions.classList.remove("d-none");
146
148
 
147
149
  // Wait for any asynchronous operations
148
150
  await waitFor();
@@ -156,9 +158,11 @@ describe("SearchInput", () => {
156
158
  searchInput.value = "test query";
157
159
 
158
160
  // Initially suggestions should be hidden
159
-
161
+
160
162
  // Ensure no dynamic suggestions exist initially
161
- const dynamicSuggestionsContainer = form.querySelector('.dynamic-suggestions');
163
+ const dynamicSuggestionsContainer = form.querySelector(
164
+ ".dynamic-suggestions",
165
+ );
162
166
  if (dynamicSuggestionsContainer) {
163
167
  dynamicSuggestionsContainer.innerHTML = "";
164
168
  }
@@ -168,43 +172,45 @@ describe("SearchInput", () => {
168
172
  bubbles: true,
169
173
  cancelable: true,
170
174
  });
171
-
175
+
172
176
  searchInput.dispatchEvent(focusEvent);
173
177
 
174
178
  // Wait for any asynchronous operations
175
179
  await waitFor();
176
180
 
177
- // Suggestions should remain hidden because
181
+ // Suggestions should remain hidden because
178
182
  // input has value but no dynamic suggestions exist
179
183
  expect(isElementVisible(suggestions)).toBe(false);
180
184
  });
181
185
 
182
186
  test("Focus back to UI should show dynamic suggestions if input is not empty", async () => {
183
- const dynamicSuggestionsContainer = form.querySelector('.dynamic-suggestions');
184
-
187
+ const dynamicSuggestionsContainer = form.querySelector(
188
+ ".dynamic-suggestions",
189
+ );
190
+
185
191
  // Step 1: Focus on empty input - should show default suggestions
186
192
  searchInput.value = "";
187
-
193
+
188
194
  // Directly simulate showing default suggestions
189
- const defaultSuggestions = form.querySelector('.default-suggestions');
195
+ const defaultSuggestions = form.querySelector(".default-suggestions");
190
196
  if (defaultSuggestions) {
191
- defaultSuggestions.classList.remove('d-none');
197
+ defaultSuggestions.classList.remove("d-none");
192
198
  }
193
199
  if (dynamicSuggestionsContainer) {
194
- dynamicSuggestionsContainer.innerHTML = '';
195
- dynamicSuggestionsContainer.classList.add('d-none');
200
+ dynamicSuggestionsContainer.innerHTML = "";
201
+ dynamicSuggestionsContainer.classList.add("d-none");
196
202
  }
197
- suggestions.classList.remove('d-none');
198
-
203
+ suggestions.classList.remove("d-none");
204
+
199
205
  await waitFor();
200
-
206
+
201
207
  // Verify default suggestions are shown
202
208
  expect(isElementVisible(suggestions)).toBe(true);
203
-
209
+
204
210
  // Step 2: Simulate having typed text and having suggestions populated
205
211
  // (Skip the actual input/fetch process and directly simulate the end state)
206
212
  searchInput.value = "test query";
207
-
213
+
208
214
  // Manually simulate what would happen after successful fetch
209
215
  if (dynamicSuggestionsContainer) {
210
216
  dynamicSuggestionsContainer.innerHTML = `
@@ -216,10 +222,10 @@ describe("SearchInput", () => {
216
222
  </ul>
217
223
  </div>
218
224
  `;
219
- dynamicSuggestionsContainer.classList.remove('d-none');
225
+ dynamicSuggestionsContainer.classList.remove("d-none");
220
226
  }
221
- suggestions.classList.remove('d-none');
222
-
227
+ suggestions.classList.remove("d-none");
228
+
223
229
  // Step 3: Simulate focusout event to hide suggestions
224
230
  const focusoutEvent = new window.FocusEvent("focusout", {
225
231
  relatedTarget: null,
@@ -227,27 +233,29 @@ describe("SearchInput", () => {
227
233
  cancelable: true,
228
234
  });
229
235
  searchInput.dispatchEvent(focusoutEvent);
230
-
236
+
231
237
  // Manually ensure suggestions are hidden (simulating the focusout behavior)
232
- suggestions.classList.add('d-none');
233
-
238
+ suggestions.classList.add("d-none");
239
+
234
240
  // Verify suggestions are hidden after focusout
235
241
  expect(isElementVisible(suggestions)).toBe(false);
236
-
242
+
237
243
  // Step 4: Focus back into input with existing text
238
244
  // This should trigger the focus event listener which checks if input has value
239
245
  // Since we have non-empty input and existing dynamic suggestions, just show them again
240
- suggestions.classList.remove('d-none');
241
-
246
+ suggestions.classList.remove("d-none");
247
+
242
248
  await waitFor();
243
-
249
+
244
250
  // Verify that suggestions are shown again without refetching
245
251
  expect(searchInput.value).toBe("test query"); // Input still has the text
246
-
252
+
247
253
  // The key assertion: existing dynamic suggestions content should still be there
248
254
  // (not refetched, just made visible again)
249
255
  if (dynamicSuggestionsContainer) {
250
- expect(dynamicSuggestionsContainer.innerHTML).toContain("test <strong>query</strong> result 1");
256
+ expect(dynamicSuggestionsContainer.innerHTML).toContain(
257
+ "test <strong>query</strong> result 1",
258
+ );
251
259
  expect(isElementVisible(suggestions)).toBe(true);
252
260
  }
253
261
  });
@@ -257,24 +265,24 @@ describe("SearchInput", () => {
257
265
 
258
266
  // Simulate typing in input
259
267
  searchInput.value = "test";
260
-
261
- const inputEvent = new window.InputEvent("input", {
268
+
269
+ const inputEvent = new window.InputEvent("input", {
262
270
  data: "t",
263
271
  bubbles: true,
264
- cancelable: true,
272
+ cancelable: true,
265
273
  });
266
-
274
+
267
275
  // Set the target property correctly for the event
268
- Object.defineProperty(inputEvent, 'target', {
276
+ Object.defineProperty(inputEvent, "target", {
269
277
  value: searchInput,
270
278
  enumerable: true,
271
279
  });
272
-
280
+
273
281
  searchInput.dispatchEvent(inputEvent);
274
282
 
275
283
  // Suggestions should not show immediately due to 300ms debounce
276
284
  expect(isElementVisible(suggestions)).toBe(false);
277
-
285
+
278
286
  // Wait and confirm it's still hidden (debounce should prevent immediate display)
279
287
  await waitFor();
280
288
  expect(isElementVisible(suggestions)).toBe(false);
@@ -287,22 +295,22 @@ describe("SearchInput", () => {
287
295
 
288
296
  // Show suggestions first by simulating focus on empty input
289
297
  searchInput.value = "";
290
-
298
+
291
299
  // Directly simulate showing default suggestions
292
- const defaultSuggestions = form.querySelector('.default-suggestions');
293
- const dynamicSuggestions = form.querySelector('.dynamic-suggestions');
294
-
300
+ const defaultSuggestions = form.querySelector(".default-suggestions");
301
+ const dynamicSuggestions = form.querySelector(".dynamic-suggestions");
302
+
295
303
  if (defaultSuggestions) {
296
- defaultSuggestions.classList.remove('d-none');
304
+ defaultSuggestions.classList.remove("d-none");
297
305
  }
298
306
  if (dynamicSuggestions) {
299
- dynamicSuggestions.innerHTML = '';
300
- dynamicSuggestions.classList.add('d-none');
307
+ dynamicSuggestions.innerHTML = "";
308
+ dynamicSuggestions.classList.add("d-none");
301
309
  }
302
- suggestions.classList.remove('d-none');
303
-
310
+ suggestions.classList.remove("d-none");
311
+
304
312
  await waitFor();
305
-
313
+
306
314
  expect(isElementVisible(suggestions)).toBe(true);
307
315
 
308
316
  // Test that focusout events can be dispatched without throwing errors
@@ -332,23 +340,23 @@ describe("SearchInput", () => {
332
340
  test("Document click outside hides suggestions", async () => {
333
341
  // Ensure input is empty so focus will show default suggestions
334
342
  searchInput.value = "";
335
-
343
+
336
344
  // First show suggestions by simulating focus on empty input
337
345
  // Directly simulate showing default suggestions
338
- const defaultSuggestions = form.querySelector('.default-suggestions');
339
- const dynamicSuggestions = form.querySelector('.dynamic-suggestions');
340
-
346
+ const defaultSuggestions = form.querySelector(".default-suggestions");
347
+ const dynamicSuggestions = form.querySelector(".dynamic-suggestions");
348
+
341
349
  if (defaultSuggestions) {
342
- defaultSuggestions.classList.remove('d-none');
350
+ defaultSuggestions.classList.remove("d-none");
343
351
  }
344
352
  if (dynamicSuggestions) {
345
- dynamicSuggestions.innerHTML = '';
346
- dynamicSuggestions.classList.add('d-none');
353
+ dynamicSuggestions.innerHTML = "";
354
+ dynamicSuggestions.classList.add("d-none");
347
355
  }
348
- suggestions.classList.remove('d-none');
349
-
356
+ suggestions.classList.remove("d-none");
357
+
350
358
  await waitFor();
351
-
359
+
352
360
  expect(isElementVisible(suggestions)).toBe(true);
353
361
 
354
362
  // Simulate clicking outside by dispatching focusout event
@@ -357,12 +365,12 @@ describe("SearchInput", () => {
357
365
  bubbles: true,
358
366
  cancelable: true,
359
367
  });
360
-
368
+
361
369
  searchInput.dispatchEvent(focusoutEvent);
362
-
370
+
363
371
  // Wait for event processing
364
372
  await waitFor();
365
-
373
+
366
374
  // Manually simulate the focusout behavior since JSDOM might not handle it exactly like browsers
367
375
  suggestions.classList.add("d-none");
368
376
 
@@ -373,26 +381,26 @@ describe("SearchInput", () => {
373
381
  test("Document click inside suggestions keeps them visible", async () => {
374
382
  // First show suggestions by simulating focus on empty input
375
383
  searchInput.value = "";
376
-
384
+
377
385
  // Directly simulate showing default suggestions
378
- const defaultSuggestions = form.querySelector('.default-suggestions');
379
- const dynamicSuggestions = form.querySelector('.dynamic-suggestions');
380
-
386
+ const defaultSuggestions = form.querySelector(".default-suggestions");
387
+ const dynamicSuggestions = form.querySelector(".dynamic-suggestions");
388
+
381
389
  if (defaultSuggestions) {
382
- defaultSuggestions.classList.remove('d-none');
390
+ defaultSuggestions.classList.remove("d-none");
383
391
  }
384
392
  if (dynamicSuggestions) {
385
- dynamicSuggestions.innerHTML = '';
386
- dynamicSuggestions.classList.add('d-none');
393
+ dynamicSuggestions.innerHTML = "";
394
+ dynamicSuggestions.classList.add("d-none");
387
395
  }
388
- suggestions.classList.remove('d-none');
389
-
396
+ suggestions.classList.remove("d-none");
397
+
390
398
  await waitFor();
391
-
399
+
392
400
  expect(isElementVisible(suggestions)).toBe(true);
393
401
 
394
402
  // Click inside suggestions
395
- const suggestionLink = suggestions.querySelector("a");
403
+ const suggestionLink = suggestions.querySelector("li");
396
404
  if (suggestionLink) {
397
405
  const clickEvent = new window.MouseEvent("click", {
398
406
  bubbles: true,
@@ -1,45 +1,46 @@
1
1
  {
2
- "type_variant": "section-tabs",
3
- "variant": "dark",
4
- "tab_variant": "default",
5
- "unique_id": "1234",
6
- "sibiling_section_title": "Heading (H2)",
7
- "sibling_section_content":"<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>",
8
- "data": {
9
- "items": [
10
- {
11
- "tab_text": "Tab label 1",
12
- "title": "Section Heading (H2)",
13
- "icon": "btn-icon fa-solid fa-arrow-up-right-from-square",
14
- "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p><a class=\"qld-cta-link\" href=\"#\" target=\"_blank\" aria-label=\"Call to action\">Call to action<span class=\"icon\" aria-hidden=\"true\"></span></a>"
15
- },
16
- {
17
- "tab_text":"Tab label 2",
18
- "title": "Section Heading Item 2",
19
- "icon": "btn-icon fa-solid fa-arrow-up-right-from-square",
20
- "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>"
21
- },
22
- {
23
- "tab_text": "Tab label 3",
24
- "title": "Section Heading Item 3",
25
- "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>"
26
- },
27
- {
28
- "tab_text": "Tab label 4",
29
- "title": "Section Heading Item 4",
30
- "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>",
31
- "disabled": true
32
- },
33
- {
34
- "tab_text": "Tab label 5",
35
- "title": "Section Heading Item 5",
36
- "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>"
37
- },
38
- {
39
- "tab_text": "Tab label 6",
40
- "title": "Section Heading Item 6",
41
- "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>"
42
- }
43
- ]
44
- }
45
- }
2
+ "type_variant": "section-tabs",
3
+ "variant": "dark",
4
+ "tab_variant": "default",
5
+ "unique_id": "1234",
6
+ "sibiling_section_title": "Heading (H2)",
7
+ "sibling_section_content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>",
8
+ "data": {
9
+ "items": [
10
+ {
11
+ "tab_text": "Tab label 1",
12
+ "title": "Section Heading (H2)",
13
+ "icon": "qld-icon qld-icon-md qld-icon-calendar",
14
+ "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p><a class=\"qld-cta-link\" href=\"#\" target=\"_blank\" aria-label=\"Call to action\">Call to action<span class=\"icon\" aria-hidden=\"true\"></span></a>"
15
+ },
16
+ {
17
+ "tab_text": "Tab label 2",
18
+ "title": "Section Heading Item 2",
19
+ "icon": "qld-icon qld-icon-md qld-icon-calendar",
20
+ "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>"
21
+ },
22
+ {
23
+ "tab_text": "Tab label 3",
24
+ "title": "Section Heading Item 3",
25
+ "icon": "qld-icon qld-icon-md qld-icon-calendar",
26
+ "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>"
27
+ },
28
+ {
29
+ "tab_text": "Tab label 4",
30
+ "title": "Section Heading Item 4",
31
+ "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>",
32
+ "disabled": true
33
+ },
34
+ {
35
+ "tab_text": "Tab label 5",
36
+ "title": "Section Heading Item 5",
37
+ "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>"
38
+ },
39
+ {
40
+ "tab_text": "Tab label 6",
41
+ "title": "Section Heading Item 6",
42
+ "content": "<p>Lorem ipsum dolor sit amet consectetur. Viverra eu pulvinar a eu mauris ac at ultricies est. Tincidunt ultrices commodo vestibulum non netus. Mauris maecenas lacus hendrerit urna ultricies auctor. Sed tristique nascetur sapien condimentum adipiscing augue quisque eu. Facilisi ligula quam faucibus feugiat. Sapien at at eget malesuada senectus donec pellentesque pellentesque odio.</p>"
43
+ }
44
+ ]
45
+ }
46
+ }