@stackoverflow/stacks 1.8.0 → 1.9.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 (137) hide show
  1. package/dist/components/activity-indicator/activity-indicator.a11y.test.d.ts +1 -0
  2. package/dist/components/activity-indicator/activity-indicator.visual.test.d.ts +1 -0
  3. package/dist/components/avatar/avatar.a11y.test.d.ts +1 -0
  4. package/dist/components/avatar/avatar.visual.test.d.ts +1 -0
  5. package/dist/{controllers/s-banner.d.ts → components/banner/banner.d.ts} +1 -1
  6. package/dist/components/banner/banner.test.d.ts +1 -0
  7. package/dist/components/banner/banner.visual.test.d.ts +1 -0
  8. package/dist/components/button/button.a11y.test.d.ts +1 -0
  9. package/dist/components/button/button.visual.test.d.ts +1 -0
  10. package/dist/{controllers/s-expandable-control.d.ts → components/expandable/expandable.d.ts} +1 -1
  11. package/dist/components/expandable/expandable.test.d.ts +1 -0
  12. package/dist/{controllers/s-modal.d.ts → components/modal/modal.d.ts} +1 -1
  13. package/dist/{controllers/s-navigation-tablist.d.ts → components/navigation/navigation.d.ts} +1 -1
  14. package/dist/{controllers/s-popover.d.ts → components/popover/popover.d.ts} +1 -1
  15. package/dist/{controllers/s-tooltip.d.ts → components/popover/tooltip.d.ts} +1 -1
  16. package/dist/components/popover/tooltip.test.d.ts +1 -0
  17. package/dist/components/popover/tooltip.visual.test.d.ts +1 -0
  18. package/dist/{controllers/s-table.d.ts → components/table/table.d.ts} +1 -1
  19. package/dist/{controllers/s-toast.d.ts → components/toast/toast.d.ts} +1 -1
  20. package/dist/components/toast/toast.test.d.ts +1 -0
  21. package/dist/components/toast/toast.visual.test.d.ts +1 -0
  22. package/dist/{controllers/s-uploader.d.ts → components/uploader/uploader.d.ts} +1 -1
  23. package/dist/controllers.d.ts +9 -0
  24. package/dist/css/stacks.css +2043 -1989
  25. package/dist/css/stacks.min.css +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/js/stacks.js +545 -545
  28. package/dist/js/stacks.min.js +1 -1
  29. package/dist/test/test-utils.d.ts +136 -0
  30. package/lib/{css/atomic/borders.less → atomic/border.less} +18 -0
  31. package/lib/{css/base/icons.less → base/icon.less} +0 -9
  32. package/lib/components/activity-indicator/activity-indicator.a11y.test.ts +21 -0
  33. package/lib/components/activity-indicator/activity-indicator.visual.test.ts +23 -0
  34. package/lib/components/avatar/avatar.a11y.test.ts +36 -0
  35. package/lib/components/avatar/avatar.visual.test.ts +54 -0
  36. package/lib/components/banner/banner.less +51 -0
  37. package/lib/{test/s-banner.test.ts → components/banner/banner.test.ts} +7 -3
  38. package/lib/{ts/controllers/s-banner.ts → components/banner/banner.ts} +1 -1
  39. package/lib/components/banner/banner.visual.test.ts +36 -0
  40. package/lib/components/button/button.a11y.test.ts +32 -0
  41. package/lib/{css/components/buttons.less → components/button/button.less} +3 -2
  42. package/lib/components/button/button.visual.test.ts +52 -0
  43. package/lib/{css/components/cards.less → components/card/card.less} +1 -1
  44. package/lib/components/check-control/check-control.less +17 -0
  45. package/lib/components/check-group/check-group.less +19 -0
  46. package/lib/{css/components → components/expandable}/expandable.less +3 -0
  47. package/lib/components/expandable/expandable.test.ts +53 -0
  48. package/lib/{ts/controllers/s-expandable-control.ts → components/expandable/expandable.ts} +1 -1
  49. package/lib/components/input-fill/input-fill.less +35 -0
  50. package/lib/components/input-icon/input-icon.less +45 -0
  51. package/lib/components/input-message/input-message.less +48 -0
  52. package/lib/{css/components/inputs.less → components/input_textarea/input_textarea.less} +0 -131
  53. package/lib/{css/components → components/link}/link.less +2 -2
  54. package/lib/{ts/controllers/s-modal.ts → components/modal/modal.ts} +1 -1
  55. package/lib/{ts/controllers/s-navigation-tablist.ts → components/navigation/navigation.ts} +1 -1
  56. package/lib/{css/components/notices.less → components/notice/notice.less} +0 -89
  57. package/lib/{css/components/popovers.less → components/popover/popover.less} +1 -0
  58. package/lib/{ts/controllers/s-popover.ts → components/popover/popover.ts} +1 -1
  59. package/lib/{test/s-tooltip.test.ts → components/popover/tooltip.test.ts} +6 -2
  60. package/lib/{ts/controllers/s-tooltip.ts → components/popover/tooltip.ts} +2 -2
  61. package/lib/{test/s-tooltip.visual.test.ts → components/popover/tooltip.visual.test.ts} +2 -2
  62. package/lib/{css/components/sidebar-widgets.less → components/sidebar-widget/sidebar-widget.less} +0 -1
  63. package/lib/{css/components → components/table}/table.less +0 -5
  64. package/lib/{ts/controllers/s-table.ts → components/table/table.ts} +1 -1
  65. package/lib/components/table-container/table-container.less +4 -0
  66. package/lib/components/toast/toast.less +35 -0
  67. package/lib/{test/s-toast.test.ts → components/toast/toast.test.ts} +7 -3
  68. package/lib/{ts/controllers/s-toast.ts → components/toast/toast.ts} +1 -1
  69. package/lib/components/toast/toast.visual.test.ts +27 -0
  70. package/lib/{ts/controllers/s-uploader.ts → components/uploader/uploader.ts} +1 -1
  71. package/lib/controllers.ts +33 -0
  72. package/lib/{ts/index.ts → index.ts} +1 -1
  73. package/lib/{css/stacks-dynamic.less → stacks-dynamic.less} +1 -2
  74. package/lib/stacks-static.less +93 -0
  75. package/lib/test/test-utils.ts +444 -0
  76. package/lib/tsconfig.json +1 -1
  77. package/package.json +17 -17
  78. package/dist/controllers/index.d.ts +0 -9
  79. package/lib/css/stacks-static.less +0 -87
  80. package/lib/test/s-avatar.a11y.test.ts +0 -77
  81. package/lib/test/s-banner.visual.test.ts +0 -61
  82. package/lib/test/s-btn.a11y.test.ts +0 -123
  83. package/lib/test/s-btn.visual.test.ts +0 -16
  84. package/lib/test/s-toast.visual.test.ts +0 -48
  85. package/lib/ts/controllers/index.ts +0 -17
  86. /package/lib/{css/atomic/colors.less → atomic/color.less} +0 -0
  87. /package/lib/{css/atomic → atomic}/flex.less +0 -0
  88. /package/lib/{css/atomic → atomic}/gap.less +0 -0
  89. /package/lib/{css/atomic → atomic}/grid.less +0 -0
  90. /package/lib/{css/atomic → atomic}/misc.less +0 -0
  91. /package/lib/{css/atomic → atomic}/spacing.less +0 -0
  92. /package/lib/{css/atomic → atomic}/typography.less +0 -0
  93. /package/lib/{css/atomic → atomic}/width-height.less +0 -0
  94. /package/lib/{css/base → base}/body.less +0 -0
  95. /package/lib/{css/base → base}/configuration-static.less +0 -0
  96. /package/lib/{css/base → base}/fieldset.less +0 -0
  97. /package/lib/{css/base/internals.less → base/internal.less} +0 -0
  98. /package/lib/{css/base → base}/reset-meyer.less +0 -0
  99. /package/lib/{css/base → base}/reset-normalize.less +0 -0
  100. /package/lib/{css/base → base}/reset.less +0 -0
  101. /package/lib/{css/components → components/activity-indicator}/activity-indicator.less +0 -0
  102. /package/lib/{css/components/anchors.less → components/anchor/anchor.less} +0 -0
  103. /package/lib/{css/components/avatars.less → components/avatar/avatar.less} +0 -0
  104. /package/lib/{css/components → components/award-bling}/award-bling.less +0 -0
  105. /package/lib/{css/components/badges.less → components/badge/badge.less} +0 -0
  106. /package/lib/{css/components → components/block-link}/block-link.less +0 -0
  107. /package/lib/{css/components → components/breadcrumbs}/breadcrumbs.less +0 -0
  108. /package/lib/{css/components/button-groups.less → components/button-group/button-group.less} +0 -0
  109. /package/lib/{css/components/checkboxes-radios.less → components/checkbox_radio/checkbox_radio.less} +0 -0
  110. /package/lib/{css/components/code-blocks.less → components/code-block/code-block.less} +0 -0
  111. /package/lib/{css/components → components/description}/description.less +0 -0
  112. /package/lib/{css/components/empty-states.less → components/empty-state/empty-state.less} +0 -0
  113. /package/lib/{css/components/labels.less → components/label/label.less} +0 -0
  114. /package/lib/{css/components/link-previews.less → components/link-preview/link-preview.less} +0 -0
  115. /package/lib/{css/components → components/menu}/menu.less +0 -0
  116. /package/lib/{css/components/modals.less → components/modal/modal.less} +0 -0
  117. /package/lib/{css/components → components/navigation}/navigation.less +0 -0
  118. /package/lib/{css/components/page-titles.less → components/page-title/page-title.less} +0 -0
  119. /package/lib/{css/components → components/pagination}/pagination.less +0 -0
  120. /package/lib/{css/components → components/post-summary}/post-summary.less +0 -0
  121. /package/lib/{css/components/progress-bars.less → components/progress-bar/progress-bar.less} +0 -0
  122. /package/lib/{css/components → components/prose}/prose.less +0 -0
  123. /package/lib/{css/components → components/select}/select.less +0 -0
  124. /package/lib/{css/components → components/spinner}/spinner.less +0 -0
  125. /package/lib/{css/components/tags.less → components/tag/tag.less} +0 -0
  126. /package/lib/{css/components/toggle-switches.less → components/toggle-switch/toggle-switch.less} +0 -0
  127. /package/lib/{css/components → components/topbar}/topbar.less +0 -0
  128. /package/lib/{css/components → components/uploader}/uploader.less +0 -0
  129. /package/lib/{css/components/user-cards.less → components/user-card/user-card.less} +0 -0
  130. /package/lib/{css/exports → exports}/constants-colors.less +0 -0
  131. /package/lib/{css/exports → exports}/constants-helpers.less +0 -0
  132. /package/lib/{css/exports → exports}/constants-type.less +0 -0
  133. /package/lib/{css/exports → exports}/exports.less +0 -0
  134. /package/lib/{css/exports → exports}/mixins.less +0 -0
  135. /package/lib/{css/input-utils.less → input-utils.less} +0 -0
  136. /package/lib/{css/stacks.less → stacks.less} +0 -0
  137. /package/lib/{ts/stacks.ts → stacks.ts} +0 -0
@@ -0,0 +1,93 @@
1
+ // stacks-static.less contains styles which we DO NOT allow communities to modify via variables
2
+ // BASE
3
+ @import "base/reset.less";
4
+ @import "base/fieldset.less";
5
+ @import "base/icon.less";
6
+ @import "input-utils.less";
7
+
8
+ // -- COMPONENTS
9
+ @import "components/activity-indicator/activity-indicator.less";
10
+ @import "components/anchor/anchor.less";
11
+ @import "components/avatar/avatar.less";
12
+ @import "components/award-bling/award-bling.less";
13
+ @import "components/badge/badge.less";
14
+ @import "components/banner/banner.less";
15
+ @import "components/block-link/block-link.less";
16
+ @import "components/breadcrumbs/breadcrumbs.less";
17
+ @import "components/button/button.less";
18
+ @import "components/button-group/button-group.less";
19
+ @import "components/card/card.less";
20
+ @import "components/check-control/check-control.less";
21
+ @import "components/check-group/check-group.less";
22
+ @import "components/checkbox_radio/checkbox_radio.less";
23
+ @import "components/code-block/code-block.less";
24
+ @import "components/description/description.less";
25
+ @import "components/empty-state/empty-state.less";
26
+ @import "components/expandable/expandable.less";
27
+ @import "components/input_textarea/input_textarea.less";
28
+ @import "components/input-fill/input-fill.less";
29
+ @import "components/input-icon/input-icon.less";
30
+ @import "components/input-message/input-message.less";
31
+ @import "components/label/label.less";
32
+ @import "components/link/link.less";
33
+ @import "components/link-preview/link-preview.less";
34
+ @import "components/menu/menu.less";
35
+ @import "components/modal/modal.less";
36
+ @import "components/navigation/navigation.less";
37
+ @import "components/notice/notice.less";
38
+ @import "components/page-title/page-title.less";
39
+ @import "components/pagination/pagination.less";
40
+ @import "components/popover/popover.less";
41
+ @import "components/post-summary/post-summary.less";
42
+ @import "components/progress-bar/progress-bar.less";
43
+ @import "components/prose/prose.less";
44
+ @import "components/select/select.less";
45
+ @import "components/sidebar-widget/sidebar-widget.less";
46
+ @import "components/spinner/spinner.less";
47
+ @import "components/table/table.less";
48
+ @import "components/table-container/table-container.less";
49
+ @import "components/tag/tag.less";
50
+ @import "components/toast/toast.less";
51
+ @import "components/toggle-switch/toggle-switch.less";
52
+ @import "components/topbar/topbar.less";
53
+ @import "components/uploader/uploader.less";
54
+ @import "components/user-card/user-card.less";
55
+
56
+ // LESS CONSTANTS AND MIXINS
57
+ @import "exports/exports.less";
58
+
59
+ // -- ATOMIC CLASSES
60
+ @import "atomic/border.less";
61
+ @import "atomic/color.less";
62
+ @import "atomic/flex.less";
63
+ @import "atomic/gap.less";
64
+ @import "atomic/grid.less";
65
+ @import "atomic/spacing.less";
66
+ @import "atomic/typography.less";
67
+ @import "atomic/misc.less";
68
+ @import "atomic/width-height.less";
69
+
70
+ /* stylelint-disable */
71
+ #stacks-internals #screen-lg({
72
+ #stacks-internals-collect-large();
73
+ });
74
+ #stacks-internals #screen-md({
75
+ #stacks-internals-collect-medium();
76
+ });
77
+ #stacks-internals #screen-sm({
78
+ #stacks-internals-collect-small();
79
+ });
80
+
81
+ @media print { // We need printing styles to be last so they can override all other styles.
82
+ .print\:d-block & {
83
+ display: block !important;
84
+ }
85
+ .print\:d-none & {
86
+ display: none !important;
87
+ }
88
+ }
89
+ /* stylelint-enable */
90
+
91
+ // CONFIG
92
+ @import "base/configuration-static.less";
93
+ @import "base/internal.less";
@@ -0,0 +1,444 @@
1
+ import { html, fixture, expect, unsafeStatic } from "@open-wc/testing";
2
+ import { screen } from "@testing-library/dom";
3
+ import { visualDiff } from "@web/test-runner-visual-regression";
4
+ import type { TemplateResult } from "lit-html";
5
+
6
+ const colorThemes = ["dark", "light"];
7
+ const baseThemes = ["", "highcontrast"];
8
+ type Themes = ["light" | "dark" | "highcontrast" | ""];
9
+ type TestTypes = "visual" | "a11y";
10
+
11
+ type TestOptions = {
12
+ /**
13
+ * Enable tests for all color themes
14
+ * default: true
15
+ */
16
+ testColorThemes: boolean;
17
+ /**
18
+ * Enable tests for high contrast
19
+ * default: true
20
+ */
21
+ testHighContrast: boolean;
22
+ /**
23
+ * Include tests for the component without any variants applied
24
+ * default: true
25
+ */
26
+ includeNullVariant: boolean;
27
+ /**
28
+ * Include tests for the component without any modifiers applied
29
+ * default: true
30
+ */
31
+ includeNullModifier: boolean;
32
+ };
33
+
34
+ interface ComponentTestVariationArgs {
35
+ /**
36
+ * Base class of the component
37
+ * (e.g. "s-component")
38
+ */
39
+ baseClass: string;
40
+ /**
41
+ * Variants of the component
42
+ * (e.g. ["primary", "secondary"])
43
+ */
44
+ variants?: string[];
45
+ /**
46
+ * Modifiers of the component
47
+ * (e.g. { primary: ["filled", "outlined"], secondary: ["xs", "sm", "md"] })
48
+ */
49
+ modifiers?: ComponentTestModifiers;
50
+ /**
51
+ * Options for the test
52
+ */
53
+ options?: TestOptions;
54
+ }
55
+
56
+ type ComponentTestArgs = {
57
+ /**
58
+ * The element to test
59
+ * use the `html` template tag to render the element
60
+ */
61
+ element: TemplateResult;
62
+ /**
63
+ * testid of the test
64
+ * (e.g. "s-component-primary-important")
65
+ */
66
+ testid: string;
67
+ /**
68
+ * Theme to apply to the test element
69
+ */
70
+ theme?: Themes;
71
+ /**
72
+ * Type of test to run
73
+ */
74
+ type: TestTypes;
75
+ };
76
+
77
+ interface ComponentTestsArgs extends ComponentTestVariationArgs {
78
+ /**
79
+ * Additional html attributes applied to the test element
80
+ * (e.g. { role: "button", id: "id" } -> <element role="button" id="id"> )
81
+ */
82
+ attributes?: Record<string, string>;
83
+ /**
84
+ * Child elements to render inside the test element
85
+ * (if key `default` is used, the testid will not include the child name)
86
+ */
87
+ children?: {
88
+ [key: string]: string;
89
+ };
90
+ /**
91
+ * testids of tests to exclude from testing
92
+ */
93
+ excludedTestids?: (string | RegExp)[];
94
+ /**
95
+ * testids of tests to skip
96
+ */
97
+ skippedTestids?: (string | RegExp)[];
98
+ /**
99
+ * HTML tag name of the test element
100
+ */
101
+ tag?: string;
102
+ /**
103
+ * Function that returns a template for the test element
104
+ * used to wrap the component test element in a container
105
+ */
106
+ template?: (args: {
107
+ component: unknown;
108
+ tag?: string;
109
+ testid: string;
110
+ }) => ReturnType<typeof html>;
111
+ /**
112
+ * Type of test to run
113
+ */
114
+ type: TestTypes;
115
+ }
116
+
117
+ type ComponentTestModifiers = {
118
+ /**
119
+ * Primary grouping of modifiers to test
120
+ * The base class will be used as a prefix for these modifiers
121
+ */
122
+ primary?: string[];
123
+ /**
124
+ * Secondary grouping of modifiers to test
125
+ * The base class will be used as a prefix for these modifiers
126
+ */
127
+ secondary?: string[];
128
+ /**
129
+ * Grouping of modifers to test that will not be prefixed with the base class
130
+ */
131
+ global?: string[];
132
+ /**
133
+ * Modifiers to test individually
134
+ * The base class will be used as a prefix for these modifiers
135
+ */
136
+ standalone?: string[];
137
+ };
138
+
139
+ type ComponentTestProps = {
140
+ classes: string;
141
+ testid: string;
142
+ theme?: Themes;
143
+ };
144
+
145
+ const attrObjToString = (attrs: Record<string, string>): string => {
146
+ const attrString = Object.keys(attrs).map((key) => {
147
+ return `${key}="${attrs[key]}"` || "";
148
+ });
149
+ return attrString.join(" ") || "";
150
+ };
151
+
152
+ const buildClasses = ({
153
+ baseClass,
154
+ prefixed = [],
155
+ unprefixed = [],
156
+ }: {
157
+ baseClass: string;
158
+ prefixed?: string[];
159
+ unprefixed?: string[];
160
+ }) =>
161
+ [
162
+ baseClass,
163
+ ...prefixed.filter((x) => x).map((suffix) => `${baseClass}__${suffix}`),
164
+ ...unprefixed.filter((x) => x),
165
+ ].join(" ");
166
+
167
+ const buildTestElement = ({
168
+ attributes = {},
169
+ children = "",
170
+ tag = "div",
171
+ testid,
172
+ }: {
173
+ attributes?: Record<string, string>;
174
+ children?: string;
175
+ tag?: string;
176
+ testid: string;
177
+ }) => {
178
+ const unsafe = {
179
+ tag: unsafeStatic(tag),
180
+ attributes: unsafeStatic(attrObjToString(attributes).toString()),
181
+ children: unsafeStatic(children),
182
+ };
183
+
184
+ return html`
185
+ <${unsafe.tag}
186
+ ${unsafe.attributes}
187
+ data-testid="${testid}"
188
+ >
189
+ ${unsafe.children}
190
+ </${unsafe.tag}>
191
+ `;
192
+ };
193
+
194
+ const buildTestid = (arr: string[]) => arr.filter(Boolean).join("-");
195
+
196
+ const getComponentTestVariations = ({
197
+ baseClass,
198
+ variants = [],
199
+ modifiers,
200
+ options = {
201
+ testColorThemes: true,
202
+ testHighContrast: true,
203
+ includeNullVariant: false,
204
+ includeNullModifier: true,
205
+ },
206
+ }: ComponentTestVariationArgs): ComponentTestProps[] => {
207
+ const testVariations: ComponentTestProps[] = [];
208
+ // Test default, high contrast themes
209
+ [...(options.testHighContrast ? baseThemes : [""])].forEach((baseTheme) => {
210
+ // Test light, dark theme
211
+ [...(options.testColorThemes ? colorThemes : [""])].forEach(
212
+ (colorTheme) => {
213
+ const theme = [baseTheme, colorTheme].filter(Boolean) as Themes;
214
+ const testidBase = buildTestid([baseClass, ...theme]);
215
+ const primaryModifiers = modifiers?.primary
216
+ ? ["", ...(<[]>modifiers.primary)]
217
+ : [""];
218
+ const secondaryModifiers = modifiers?.secondary
219
+ ? ["", ...(<[]>modifiers.secondary)]
220
+ : [""];
221
+ const globalModifiers = modifiers?.global
222
+ ? ["", ...(<[]>modifiers.global)]
223
+ : [""];
224
+
225
+ primaryModifiers.forEach((primaryModifier) => {
226
+ secondaryModifiers.forEach((secondaryModifier) => {
227
+ globalModifiers.forEach((globalModifier) => {
228
+ ["", ...variants].forEach((variant) => {
229
+ testVariations.push({
230
+ classes: buildClasses({
231
+ baseClass,
232
+ prefixed: [
233
+ variant,
234
+ primaryModifier,
235
+ secondaryModifier,
236
+ ],
237
+ unprefixed: [globalModifier],
238
+ }),
239
+ testid: buildTestid([
240
+ testidBase,
241
+ variant,
242
+ [
243
+ primaryModifier,
244
+ secondaryModifier,
245
+ globalModifier,
246
+ ]
247
+ .filter(Boolean)
248
+ .join("-"),
249
+ ]),
250
+ theme,
251
+ });
252
+ });
253
+ });
254
+ });
255
+ });
256
+
257
+ // create standalone modifiers test props
258
+ modifiers?.standalone?.forEach((standaloneModifier) => {
259
+ testVariations.push({
260
+ testid: buildTestid([testidBase, standaloneModifier]),
261
+ classes: buildClasses({
262
+ baseClass,
263
+ prefixed: [standaloneModifier],
264
+ }),
265
+ theme,
266
+ });
267
+ });
268
+ }
269
+ );
270
+ });
271
+
272
+ // Sorting for readability
273
+ return testVariations.sort((a, b) => a.testid.localeCompare(b.testid));
274
+ };
275
+
276
+ /**
277
+ * Constructs and runs an individual test for a component
278
+ */
279
+ const runComponentTest = ({
280
+ element,
281
+ testid,
282
+ theme,
283
+ type,
284
+ }: ComponentTestArgs) => {
285
+ const getDescription = (type: TestTypes) => {
286
+ switch (type) {
287
+ case "a11y":
288
+ return "should be accessible";
289
+ case "visual":
290
+ return "should not introduce visual regressions";
291
+ default:
292
+ return "";
293
+ }
294
+ };
295
+
296
+ it(`${type}: ${testid} ${getDescription(type)}`, async () => {
297
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
298
+ await fixture(element);
299
+ const el = screen.getByTestId(testid);
300
+
301
+ document.body.className = "";
302
+
303
+ if (theme?.length) {
304
+ const prefixedThemes = theme.map((t) => `theme-${t}`);
305
+ document.body.classList.add(...prefixedThemes);
306
+ }
307
+
308
+ if (type === "a11y") {
309
+ // TODO add conditional option for high contrast mode to test against AAA
310
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
311
+ await expect(el).to.be.accessible();
312
+ }
313
+
314
+ if (type === "visual") {
315
+ await visualDiff(el, testid);
316
+ }
317
+ });
318
+ };
319
+
320
+ /**
321
+ * Constructs and runs tests for a component with a each provided combination
322
+ */
323
+ const runComponentTests = ({
324
+ baseClass,
325
+ variants = [],
326
+ modifiers,
327
+ options = {
328
+ testColorThemes: true,
329
+ testHighContrast: true,
330
+ includeNullVariant: false,
331
+ includeNullModifier: true,
332
+ },
333
+ attributes,
334
+ children,
335
+ excludedTestids = [],
336
+ skippedTestids = [],
337
+ tag,
338
+ template,
339
+ type,
340
+ }: ComponentTestsArgs) => {
341
+ getComponentTestVariations({
342
+ baseClass,
343
+ variants,
344
+ modifiers,
345
+ options,
346
+ }).forEach(({ testid, classes, theme }) => {
347
+ const allChildren: {
348
+ [key: string]: string;
349
+ } = children ? { ...children } : { default: "" };
350
+
351
+ Object.keys(allChildren).forEach((key) => {
352
+ const testidModified =
353
+ key !== "default" ? `${testid}-${key}` : testid;
354
+ const children = allChildren[key];
355
+
356
+ const shouldSkipTest = excludeOrSkipTest({
357
+ patterns: skippedTestids,
358
+ skip: true,
359
+ testid: testidModified,
360
+ type,
361
+ });
362
+
363
+ const shouldExcludeTest = excludeOrSkipTest({
364
+ patterns: excludedTestids,
365
+ testid: testidModified,
366
+ type,
367
+ });
368
+
369
+ if (shouldSkipTest || shouldExcludeTest) {
370
+ return;
371
+ }
372
+
373
+ const element = template
374
+ ? html`${template({
375
+ testid: testidModified,
376
+ component: buildTestElement({
377
+ attributes: {
378
+ class: classes,
379
+ ...attributes,
380
+ },
381
+ children,
382
+ testid: `${testidModified}-nested`,
383
+ tag,
384
+ }),
385
+ })}`
386
+ : buildTestElement({
387
+ attributes: {
388
+ class: classes,
389
+ ...attributes,
390
+ },
391
+ children,
392
+ testid: testidModified,
393
+ tag,
394
+ });
395
+
396
+ runComponentTest({
397
+ element,
398
+ testid: testidModified,
399
+ theme,
400
+ type,
401
+ });
402
+ });
403
+ });
404
+ };
405
+
406
+ const matchTestidByPattern = ({
407
+ testid,
408
+ pattern,
409
+ }: {
410
+ testid: string;
411
+ pattern: string | RegExp;
412
+ }): boolean => {
413
+ if (pattern instanceof RegExp) {
414
+ return pattern.test(testid);
415
+ } else {
416
+ return pattern === testid;
417
+ }
418
+ };
419
+
420
+ const excludeOrSkipTest = ({
421
+ patterns,
422
+ skip = false,
423
+ testid,
424
+ type,
425
+ }: {
426
+ patterns: (string | RegExp)[];
427
+ skip?: boolean;
428
+ testid: string;
429
+ type: TestTypes;
430
+ }): boolean => {
431
+ const matchesTest = patterns.some((pattern) => {
432
+ return matchTestidByPattern({ testid, pattern });
433
+ });
434
+
435
+ if (matchesTest && skip) {
436
+ it.skip(`${type}: ${testid} (skipped)`, () => {
437
+ return;
438
+ });
439
+ }
440
+
441
+ return matchesTest;
442
+ };
443
+
444
+ export { runComponentTest, runComponentTests };
package/lib/tsconfig.json CHANGED
@@ -9,5 +9,5 @@
9
9
  "skipLibCheck": true,
10
10
  "declaration": true
11
11
  },
12
- "include": ["ts/**/*"]
12
+ "include": ["**/*.ts"]
13
13
  }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "https://github.com/StackExchange/Stacks.git"
7
7
  },
8
- "version": "1.8.0",
8
+ "version": "1.9.0",
9
9
  "files": [
10
10
  "dist",
11
11
  "lib"
@@ -13,7 +13,7 @@
13
13
  "main": "./dist/js/stacks.js",
14
14
  "types": "./dist/index.d.ts",
15
15
  "style": "./dist/css/stacks.css",
16
- "less": "./lib/css/stacks.less",
16
+ "less": "./lib/stacks.less",
17
17
  "unpkg": "dist/css/stacks.min.css",
18
18
  "scripts": {
19
19
  "start": "concurrently -n w: npm:start:*",
@@ -30,8 +30,8 @@
30
30
  "test:visual:update": "web-test-runner --group=visual --update-visual-baseline",
31
31
  "prepublishOnly": "npm run build",
32
32
  "lint": "concurrently -n w: npm:lint:*",
33
- "lint:ts": "eslint ./lib/ts",
34
- "lint:css": "stylelint ./lib/css",
33
+ "lint:ts": "eslint ./lib/**/*.ts",
34
+ "lint:css": "stylelint ./lib/*",
35
35
  "lint:format": "prettier --check ./lib"
36
36
  },
37
37
  "license": "MIT",
@@ -45,27 +45,27 @@
45
45
  "@open-wc/testing": "^3.1.7",
46
46
  "@rollup/plugin-commonjs": "^24.0.1",
47
47
  "@rollup/plugin-replace": "^5.0.2",
48
- "@stackoverflow/stacks-editor": "^0.8.5",
48
+ "@stackoverflow/stacks-editor": "^0.8.6",
49
49
  "@stackoverflow/stacks-icons": "^5.3.1",
50
- "@testing-library/dom": "^9.0.0",
50
+ "@testing-library/dom": "^9.0.1",
51
51
  "@testing-library/user-event": "^14.4.3",
52
- "@typescript-eslint/eslint-plugin": "^5.52.0",
53
- "@typescript-eslint/parser": "^5.52.0",
54
- "@web/dev-server-esbuild": "^0.3.3",
55
- "@web/dev-server-rollup": "0.3.21",
56
- "@web/test-runner": "^0.15.0",
52
+ "@typescript-eslint/eslint-plugin": "^5.56.0",
53
+ "@typescript-eslint/parser": "^5.54.0",
54
+ "@web/dev-server-esbuild": "^0.3.4",
55
+ "@web/dev-server-rollup": "^0.4.0",
56
+ "@web/test-runner": "^0.15.1",
57
57
  "@web/test-runner-playwright": "^0.9.0",
58
58
  "@web/test-runner-visual-regression": "^0.7.0",
59
59
  "concurrently": "^7.6.0",
60
60
  "css-loader": "^6.7.3",
61
- "cssnano": "^5.1.14",
61
+ "cssnano": "^5.1.15",
62
62
  "docsearch.js": "^2.6.3",
63
63
  "eleventy-plugin-highlightjs": "^1.1.0",
64
64
  "eleventy-plugin-nesting-toc": "^1.3.0",
65
- "eslint": "^8.34.0",
66
- "eslint-config-prettier": "^8.6.0",
65
+ "eslint": "^8.36.0",
66
+ "eslint-config-prettier": "^8.7.0",
67
67
  "eslint-plugin-no-unsanitized": "^4.0.2",
68
- "jquery": "^3.6.3",
68
+ "jquery": "^3.6.4",
69
69
  "less-loader": "^11.1.0",
70
70
  "list.js": "^2.3.1",
71
71
  "markdown-it": "^13.0.1",
@@ -74,13 +74,13 @@
74
74
  "postcss-loader": "^7.0.2",
75
75
  "prettier": "^2.8.4",
76
76
  "rollup-plugin-postcss": "^4.0.2",
77
- "stylelint": "^15.2.0",
77
+ "stylelint": "^15.3.0",
78
78
  "stylelint-config-recommended": "^10.0.1",
79
79
  "stylelint-config-standard": "^30.0.1",
80
80
  "terser-webpack-plugin": "^5.3.6",
81
81
  "ts-loader": "^9.4.2",
82
82
  "typescript": "^4.9.5",
83
- "webpack": "^5.75.0",
83
+ "webpack": "^5.76.1",
84
84
  "webpack-cli": "^5.0.1",
85
85
  "webpack-merge": "^5.8.0"
86
86
  },
@@ -1,9 +0,0 @@
1
- export { ExpandableController } from "./s-expandable-control";
2
- export { hideModal, ModalController, showModal } from "./s-modal";
3
- export { hideBanner, BannerController, showBanner } from "./s-banner";
4
- export { hideToast, ToastController, showToast } from "./s-toast";
5
- export { TabListController } from "./s-navigation-tablist";
6
- export { attachPopover, detachPopover, hidePopover, BasePopoverController, PopoverController, showPopover, } from "./s-popover";
7
- export { TableController } from "./s-table";
8
- export { setTooltipHtml, setTooltipText, TooltipController } from "./s-tooltip";
9
- export { UploaderController } from "./s-uploader";