@stackoverflow/stacks 1.10.1 → 1.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/js/stacks.js CHANGED
@@ -6560,6 +6560,7 @@ class UploaderController extends StacksController {
6560
6560
  let thumbElement;
6561
6561
  if (file.type.match("image/*") && file.data) {
6562
6562
  thumbElement = document.createElement("img");
6563
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
6563
6564
  thumbElement.src = file.data.toString();
6564
6565
  thumbElement.alt = file.name;
6565
6566
  }
@@ -0,0 +1,121 @@
1
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
2
+ // import { Icons } from "@stackoverflow/stacks-icons";
3
+ import "../../index";
4
+
5
+ const variants = {
6
+ blings: ["gold", "silver", "bronze"],
7
+ numbers: ["answered", "bounty", "important", "rep", "rep-down", "votes"],
8
+ states: {
9
+ filled: ["danger", "muted"],
10
+ other: ["info", "warning"],
11
+ },
12
+ users: ["admin", "moderator", "staff"],
13
+ };
14
+
15
+ describe("badge", () => {
16
+ // Award badges (Default/badge counts)
17
+ variants.blings.map((bling) => {
18
+ runComponentTests({
19
+ type: "a11y",
20
+ baseClass: "s-badge",
21
+ variants: [bling],
22
+ children: {
23
+ default: `<span class="s-award-bling s-award-bling__${bling}">
24
+ Altruist
25
+ </span>`,
26
+ },
27
+ tag: "span",
28
+ });
29
+ });
30
+
31
+ // Number counts
32
+ runComponentTests({
33
+ type: "a11y",
34
+ baseClass: "s-badge",
35
+ variants: variants.numbers,
36
+ children: {
37
+ default: "123",
38
+ },
39
+ options: {
40
+ ...defaultOptions,
41
+ includeNullModifier: false,
42
+ },
43
+ tag: "span",
44
+ skippedTestids: [
45
+ "s-badge-dark-answered", // TODO remove when contrast bugs are fixed
46
+ "s-badge-dark-important", // TODO remove when contrast bugs are fixed
47
+ "s-badge-dark-rep-down", // TODO remove when contrast bugs are fixed
48
+ "s-badge-light-answered", // TODO remove when contrast bugs are fixed
49
+ "s-badge-light-rep", // TODO remove when contrast bugs are fixed
50
+ ],
51
+ });
52
+
53
+ // Icon badges
54
+ runComponentTests({
55
+ type: "a11y",
56
+ baseClass: "s-badge",
57
+ variants: [...variants.states.filled, ...variants.states.other],
58
+ modifiers: {
59
+ primary: ["icon"],
60
+ },
61
+ children: {
62
+ default: "with icon",
63
+ // icon: Icons.IconEyeSm, // TODO fix the icon imports
64
+ },
65
+ options: {
66
+ ...defaultOptions,
67
+ includeNullModifier: false,
68
+ },
69
+ tag: "span",
70
+ });
71
+
72
+ // Filled badges
73
+ runComponentTests({
74
+ type: "a11y",
75
+ baseClass: "s-badge",
76
+ variants: variants.states.filled,
77
+ modifiers: {
78
+ primary: ["icon"],
79
+ },
80
+ children: {
81
+ default: "filled",
82
+ // icon: Icons.IconEyeOffSm, // TODO fix the icon imports
83
+ },
84
+ options: {
85
+ ...defaultOptions,
86
+ includeNullModifier: false,
87
+ includeNullVariant: false,
88
+ },
89
+ tag: "span",
90
+ });
91
+
92
+ // User badges
93
+ runComponentTests({
94
+ type: "a11y",
95
+ baseClass: "s-badge",
96
+ variants: variants.users,
97
+ modifiers: {
98
+ primary: ["xs", "sm"],
99
+ },
100
+ children: {
101
+ default: "user",
102
+ },
103
+ tag: "span",
104
+ skippedTestids: [
105
+ /^s-badge-dark-admin.*/, // TODO remove when contrast bugs are fixed
106
+ ],
107
+ });
108
+
109
+ // Sizes
110
+ runComponentTests({
111
+ type: "a11y",
112
+ baseClass: "s-badge",
113
+ modifiers: {
114
+ primary: ["xs", "sm"],
115
+ },
116
+ children: {
117
+ default: "size badge",
118
+ },
119
+ tag: "span",
120
+ });
121
+ });
@@ -0,0 +1,128 @@
1
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
2
+ // import { Icons } from "@stackoverflow/stacks-icons";
3
+ import "../../index";
4
+ import { html } from "@open-wc/testing";
5
+
6
+ const variants = {
7
+ blings: ["gold", "silver", "bronze"],
8
+ numbers: ["answered", "bounty", "important", "rep", "rep-down", "votes"],
9
+ states: {
10
+ filled: ["danger", "muted"],
11
+ other: ["info", "warning"],
12
+ },
13
+ users: ["admin", "moderator", "staff"],
14
+ };
15
+
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ const template = ({ component, testid }: any) => html`
18
+ <div
19
+ class="d-inline-flex ai-center jc-center hs1 ws1 p8"
20
+ data-testid="${testid}"
21
+ >
22
+ ${component}
23
+ </div>
24
+ `;
25
+
26
+ describe("badge", () => {
27
+ // Award badges (Default/badge counts)
28
+ variants.blings.map((bling) => {
29
+ runComponentTests({
30
+ type: "visual",
31
+ baseClass: "s-badge",
32
+ variants: [bling],
33
+ children: {
34
+ default: `<span class="s-award-bling s-award-bling__${bling}">
35
+ Altruist
36
+ </span>`,
37
+ },
38
+ tag: "span",
39
+ template,
40
+ });
41
+ });
42
+
43
+ // Number counts
44
+ runComponentTests({
45
+ type: "visual",
46
+ baseClass: "s-badge",
47
+ variants: variants.numbers,
48
+ children: {
49
+ default: "123",
50
+ },
51
+ options: {
52
+ ...defaultOptions,
53
+ includeNullModifier: false,
54
+ },
55
+ tag: "span",
56
+ template,
57
+ });
58
+
59
+ // Icon badges
60
+ runComponentTests({
61
+ type: "visual",
62
+ baseClass: "s-badge",
63
+ variants: [...variants.states.filled, ...variants.states.other],
64
+ modifiers: {
65
+ primary: ["icon"],
66
+ },
67
+ children: {
68
+ default: "with icon",
69
+ // icon: Icons.IconEyeSm, // TODO fix the icon imports
70
+ },
71
+ options: {
72
+ ...defaultOptions,
73
+ includeNullModifier: false,
74
+ },
75
+ tag: "span",
76
+ template,
77
+ });
78
+
79
+ // Filled badges
80
+ runComponentTests({
81
+ type: "visual",
82
+ baseClass: "s-badge",
83
+ variants: variants.states.filled,
84
+ modifiers: {
85
+ primary: ["icon"],
86
+ },
87
+ children: {
88
+ default: "filled",
89
+ // icon: Icons.IconEyeOffSm, // TODO fix the icon imports
90
+ },
91
+ options: {
92
+ ...defaultOptions,
93
+ includeNullModifier: false,
94
+ includeNullVariant: false,
95
+ },
96
+ tag: "span",
97
+ template,
98
+ });
99
+
100
+ // User badges
101
+ runComponentTests({
102
+ type: "visual",
103
+ baseClass: "s-badge",
104
+ variants: variants.users,
105
+ modifiers: {
106
+ primary: ["xs", "sm"],
107
+ },
108
+ children: {
109
+ default: "user badge",
110
+ },
111
+ tag: "span",
112
+ template,
113
+ });
114
+
115
+ // Sizes
116
+ runComponentTests({
117
+ type: "visual",
118
+ baseClass: "s-badge",
119
+ modifiers: {
120
+ primary: ["xs", "sm"],
121
+ },
122
+ children: {
123
+ default: "size badge",
124
+ },
125
+ tag: "span",
126
+ template,
127
+ });
128
+ });
@@ -0,0 +1,40 @@
1
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
2
+ import "../../index";
3
+
4
+ ["checkbox", "radio"].forEach((type) => {
5
+ describe("s-check-control", () => {
6
+ // TODO include indeterminate
7
+ ["checked", "unchecked"].forEach((state) => {
8
+ runComponentTests({
9
+ type: "a11y",
10
+ baseClass: "s-check-control",
11
+ modifiers: {
12
+ global: ["has-warning", "has-error", "has-success"],
13
+ },
14
+ children: {
15
+ default: `
16
+ <input
17
+ class="s-${type}"
18
+ type="${type}"
19
+ id="test-input"
20
+ name=""
21
+ ${state === "checked" ? "checked" : ""}/>
22
+ <label class="s-label" for="test-input">
23
+ Label ${type}
24
+ <p class="s-input-message">Description</p>
25
+ </label>
26
+ `,
27
+ },
28
+ options: {
29
+ ...defaultOptions,
30
+ testidSuffix: `${state}-${type}`,
31
+ },
32
+ // TODO remove when contrast bugs are fixed
33
+ skippedTestids: [
34
+ /^s-check-control-dark-has-error-(checked|unchecked)-(checkbox|radio)$/,
35
+ /^s-check-control-light-has-(success|warning)-(checked|unchecked)-(checkbox|radio)$/,
36
+ ],
37
+ });
38
+ });
39
+ });
40
+ });
@@ -0,0 +1,38 @@
1
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
2
+ import "../../index";
3
+
4
+ ["checkbox", "radio"].forEach((type) => {
5
+ describe("s-check-control", () => {
6
+ // TODO include indeterminate
7
+ ["checked", "unchecked"].forEach((state) => {
8
+ runComponentTests({
9
+ type: "visual",
10
+ baseClass: "s-check-control",
11
+ modifiers: {
12
+ global: ["has-warning", "has-error", "has-success"],
13
+ },
14
+ attributes: {
15
+ class: "bg-black-100 hs1 ws2 p8",
16
+ },
17
+ children: {
18
+ default: `
19
+ <input
20
+ class="s-${type}"
21
+ type="${type}"
22
+ id="test-input"
23
+ name=""
24
+ ${state === "checked" ? "checked" : ""}/>
25
+ <label class="s-label" for="test-input">
26
+ Label ${type}
27
+ <p class="s-input-message">Description</p>
28
+ </label>
29
+ `,
30
+ },
31
+ options: {
32
+ ...defaultOptions,
33
+ testidSuffix: `${state}-${type}`,
34
+ },
35
+ });
36
+ });
37
+ });
38
+ });
@@ -0,0 +1,51 @@
1
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
2
+ import "../../index";
3
+
4
+ type CheckGroup = "checkbox" | "radio";
5
+ const checkTypes: CheckGroup[] = ["checkbox", "radio"];
6
+
7
+ checkTypes.forEach((type) => {
8
+ describe("s-check-group", () => {
9
+ const checkEls: {
10
+ type: CheckGroup;
11
+ id: string;
12
+ state?: "checked" | "unchecked" | "indeterminate";
13
+ }[] = [
14
+ { type, id: `test-${type}1`, state: "checked" },
15
+ { type, id: `test-${type}2` },
16
+ ];
17
+ runComponentTests({
18
+ type: "a11y",
19
+ tag: "fieldset",
20
+ baseClass: "s-check-group",
21
+ variants: ["horizontal"],
22
+ children: {
23
+ default: `
24
+ <legend class="s-label">${type} group</legend>
25
+ ${checkEls
26
+ .map(
27
+ ({ type, state, id }, index) => `
28
+ <div class="s-check-control">
29
+ <input
30
+ class="s-${type}"
31
+ type="${type}"
32
+ id="${id}-${index}"
33
+ name=""
34
+ ${state === "checked" ? "checked" : ""}/>
35
+ <label class="s-label" for="${id}-${index}">
36
+ ${type} label ${index}
37
+ <p class="s-input-message">Description</p>
38
+ </label>
39
+ </div>
40
+ `
41
+ )
42
+ .join("")}
43
+ `,
44
+ },
45
+ options: {
46
+ ...defaultOptions,
47
+ testidSuffix: type,
48
+ },
49
+ });
50
+ });
51
+ });
@@ -0,0 +1,58 @@
1
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
2
+ import "../../index";
3
+
4
+ type CheckGroup = "checkbox" | "radio";
5
+ const checkTypes: CheckGroup[] = ["checkbox", "radio"];
6
+
7
+ // Account for horizontal variant
8
+ [true, false].forEach((isHorizontal) => {
9
+ checkTypes.forEach((type) => {
10
+ describe("s-check-group", () => {
11
+ const checkEls: {
12
+ type: CheckGroup;
13
+ id: string;
14
+ state?: "checked" | "unchecked" | "indeterminate";
15
+ }[] = [
16
+ { type, id: `test-${type}1`, state: "checked" },
17
+ { type, id: `test-${type}2` },
18
+ ];
19
+ runComponentTests({
20
+ type: "visual",
21
+ tag: "fieldset",
22
+ baseClass: "s-check-group",
23
+ attributes: {
24
+ class: isHorizontal ? "hs1 ws3 p8" : "hs2 ws2 p8",
25
+ },
26
+ variants: isHorizontal ? ["horizontal"] : [],
27
+ children: {
28
+ default: `
29
+ <legend class="s-label">${type} group</legend>
30
+ ${checkEls
31
+ .map(
32
+ ({ type, state, id }, index) => `
33
+ <div class="s-check-control">
34
+ <input
35
+ class="s-${type}"
36
+ type="${type}"
37
+ id="${id}-${index}"
38
+ name=""
39
+ ${state === "checked" ? "checked" : ""}/>
40
+ <label class="s-label" for="${id}-${index}">
41
+ ${type} label ${index}
42
+ <p class="s-input-message">Description</p>
43
+ </label>
44
+ </div>
45
+ `
46
+ )
47
+ .join("")}
48
+ `,
49
+ },
50
+ options: {
51
+ ...defaultOptions,
52
+ includeNullVariant: !isHorizontal,
53
+ testidSuffix: type,
54
+ },
55
+ });
56
+ });
57
+ });
58
+ });
@@ -0,0 +1,39 @@
1
+ import { html } from "@open-wc/testing";
2
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
3
+ import "../../index";
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ const checkboxTemplate = ({ component, testid, id }: any) =>
7
+ html` <div class="s-check-control" data-testid="${testid}">
8
+ ${component}
9
+ <label class="s-label" for="${id}">Label</label>
10
+ </div>`;
11
+
12
+ ["checkbox", "radio"].forEach((type) => {
13
+ describe(type, () => {
14
+ // TODO include indeterminate
15
+ ["checked", "unchecked"].forEach((state) => {
16
+ runComponentTests({
17
+ type: "a11y",
18
+ tag: "input",
19
+ baseClass: `s-${type}`,
20
+ attributes: {
21
+ name: "test-name",
22
+ id: "test-id",
23
+ type,
24
+ ...(state === "checked" ? { checked: "checked" } : {}),
25
+ },
26
+ template: ({ component, testid }) =>
27
+ checkboxTemplate({
28
+ component,
29
+ testid,
30
+ id: "test-id",
31
+ }),
32
+ options: {
33
+ ...defaultOptions,
34
+ testidSuffix: state,
35
+ },
36
+ });
37
+ });
38
+ });
39
+ });
@@ -0,0 +1,35 @@
1
+ import { html } from "@open-wc/testing";
2
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
3
+ import "../../index";
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ const checkboxTemplate = ({ component, testid }: any) =>
7
+ html`<div
8
+ class="d-inline-flex ai-center jc-center bg-black-100 hs1 ws1 p8"
9
+ data-testid="${testid}"
10
+ >
11
+ ${component}
12
+ </div>`;
13
+
14
+ ["checkbox", "radio"].forEach((type) => {
15
+ describe(type, () => {
16
+ // TODO include indeterminate
17
+ ["checked", "unchecked"].forEach((state) => {
18
+ runComponentTests({
19
+ type: "visual",
20
+ tag: "input",
21
+ baseClass: `s-${type}`,
22
+ attributes: {
23
+ type,
24
+ ...(state === "checked" ? { checked: "checked" } : {}),
25
+ },
26
+ template: ({ component, testid }) =>
27
+ checkboxTemplate({ component, testid }),
28
+ options: {
29
+ ...defaultOptions,
30
+ testidSuffix: state,
31
+ },
32
+ });
33
+ });
34
+ });
35
+ });
@@ -0,0 +1,30 @@
1
+ import { html } from "@open-wc/testing";
2
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
3
+ import "../../index";
4
+
5
+ // account for parent with `.is-disabled` class
6
+ [true, false].forEach((isDisabled) => {
7
+ describe("description", () => {
8
+ runComponentTests({
9
+ type: "a11y",
10
+ tag: "p",
11
+ baseClass: "s-description",
12
+ children: {
13
+ default: `Describes the site in the product, emails, integrations, and logs.`,
14
+ },
15
+ options: {
16
+ ...defaultOptions,
17
+ testidSuffix: isDisabled ? "is-disabled" : "",
18
+ },
19
+ template: ({ component, testid }) => html`
20
+ <div
21
+ class="${isDisabled ? "is-disabled" : ""}"
22
+ data-testid="${testid}"
23
+ >
24
+ ${component}
25
+ </div>
26
+ `,
27
+ skippedTestids: [/^.*-is-disabled$/],
28
+ });
29
+ });
30
+ });
@@ -0,0 +1,30 @@
1
+ import { html } from "@open-wc/testing";
2
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
3
+ import "../../index";
4
+
5
+ // account for parent with `.is-disabled` class
6
+ [true, false].forEach((isDisabled) => {
7
+ describe("description", () => {
8
+ runComponentTests({
9
+ type: "visual",
10
+ tag: "p",
11
+ baseClass: "s-description",
12
+ children: {
13
+ default: `Describes the site in the product, emails, integrations, and logs.`,
14
+ },
15
+ options: {
16
+ ...defaultOptions,
17
+ testidSuffix: isDisabled ? "is-disabled" : "",
18
+ },
19
+ template: ({ component, testid }) => html`
20
+ <div
21
+ class="bg-black-100 d-inline-flex ai-center jc-center hs1 ws2 p8
22
+ ${isDisabled ? "is-disabled" : ""}"
23
+ data-testid="${testid}"
24
+ >
25
+ ${component}
26
+ </div>
27
+ `,
28
+ });
29
+ });
30
+ });
@@ -0,0 +1,73 @@
1
+ import { html } from "@open-wc/testing";
2
+ import { defaultOptions, runComponentTests } from "../../test/test-utils";
3
+ import "../../index";
4
+
5
+ describe("toggle-switch", () => {
6
+ // Single toggle switch
7
+ [true, false].forEach((checked) => {
8
+ [true, false].forEach((disabled) => {
9
+ const idSuffix = `${checked ? "-checked" : ""}${
10
+ disabled ? "-disabled" : ""
11
+ }`;
12
+ const id = `toggle-switch${idSuffix}`;
13
+
14
+ runComponentTests({
15
+ type: "a11y",
16
+ baseClass: "s-toggle-switch",
17
+ modifiers: {
18
+ global: idSuffix ? [idSuffix.substring(1)] : [], // for proper testid generation
19
+ },
20
+ tag: "input",
21
+ attributes: {
22
+ id,
23
+ type: "checkbox",
24
+ ...(checked ? { checked: "" } : {}),
25
+ ...(disabled ? { disabled: "" } : {}),
26
+ },
27
+ template: ({ component, testid }) => html`
28
+ <div data-testid="${testid}">
29
+ <label for="${id}">toggle</label>
30
+ ${component}
31
+ </div>
32
+ `,
33
+ });
34
+ });
35
+ });
36
+
37
+ // Multiple toggle switch variant
38
+ [true, false].forEach((offChecked) => {
39
+ runComponentTests({
40
+ type: "a11y",
41
+ baseClass: "s-toggle-switch",
42
+ variants: ["multiple"],
43
+ modifiers: {
44
+ global: offChecked ? ["off"] : [], // for proper testid generation
45
+ },
46
+ children: {
47
+ default: `
48
+ <input type="radio" name="group" id="four" ${
49
+ offChecked ? 'checked=""' : ""
50
+ }>
51
+ <label for="four" class="s-toggle-switch--label-off">Off</label>
52
+ <input type="radio" name="group" id="one" ${
53
+ !offChecked ? 'checked=""' : ""
54
+ }>
55
+ <label for="one">one</label>
56
+ <input type="radio" name="group" id="two">
57
+ <label for="two">two</label>
58
+ `,
59
+ },
60
+ options: {
61
+ ...defaultOptions,
62
+ includeNullVariant: false,
63
+ },
64
+ template: ({ component, testid }) => html`
65
+ <div data-testid="${testid}">${component}</div>
66
+ `,
67
+ skippedTestids: [
68
+ "s-toggle-switch-dark-multiple", // TODO fix contrast issue
69
+ "s-toggle-switch-light-multiple", // TODO fix contrast issue
70
+ ],
71
+ });
72
+ });
73
+ });
@@ -5,7 +5,8 @@
5
5
  --_ts-multiple-bg: unset;
6
6
  --_ts-multiple-fc: var(--black-500);
7
7
 
8
- fieldset[disabled] & {
8
+ fieldset[disabled] &,
9
+ &[disabled] {
9
10
  &,
10
11
  & label {
11
12
  cursor: not-allowed;