@noctuatech/uswds 0.0.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.
- package/LICENSE +21 -0
- package/README.md +25 -0
- package/package.json +89 -0
- package/src/lib/alert/alert-types.ts +33 -0
- package/src/lib/alert/alert.element.ts +105 -0
- package/src/lib/alert/alert.stories.ts +63 -0
- package/src/lib/alert/alert.test.ts +23 -0
- package/src/lib/button/button.element.ts +224 -0
- package/src/lib/button/button.stories.ts +34 -0
- package/src/lib/button/button.test.ts +17 -0
- package/src/lib/checkbox/checkbox.element.ts +166 -0
- package/src/lib/checkbox/checkbox.stories.ts +57 -0
- package/src/lib/checkbox/checkbox.test.ts +47 -0
- package/src/lib/config/config.element.ts +31 -0
- package/src/lib/config/config.test.ts +15 -0
- package/src/lib/define.ts +14 -0
- package/src/lib/description/description.element.ts +22 -0
- package/src/lib/description/description.test.ts +15 -0
- package/src/lib/file-input/file-input-preview.element.ts +121 -0
- package/src/lib/file-input/file-input-preview.test.ts +95 -0
- package/src/lib/file-input/file-input.element.ts +140 -0
- package/src/lib/file-input/file-input.stories.ts +46 -0
- package/src/lib/file-input/file-input.test.ts +47 -0
- package/src/lib/icon/icon-types.ts +263 -0
- package/src/lib/icon/icon.element.ts +65 -0
- package/src/lib/icon/icon.stories.ts +50 -0
- package/src/lib/input/input.element.ts +138 -0
- package/src/lib/input/input.stories.ts +30 -0
- package/src/lib/input/input.test.ts +48 -0
- package/src/lib/input-mask/format.ts +56 -0
- package/src/lib/input-mask/input-mask.element.ts +93 -0
- package/src/lib/input-mask/input-mask.stories.ts +38 -0
- package/src/lib/input-mask/input-mask.test.ts +106 -0
- package/src/lib/input-mask/maskable.element.ts +5 -0
- package/src/lib/link/link.element.ts +62 -0
- package/src/lib/link/link.stories.ts +30 -0
- package/src/lib/radio/radio-option.element.ts +46 -0
- package/src/lib/radio/radio-option.test.ts +20 -0
- package/src/lib/radio/radio.element.ts +152 -0
- package/src/lib/radio/radio.stories.ts +47 -0
- package/src/lib/radio/radio.test.ts +174 -0
- package/src/lib/select/select-option.element.ts +40 -0
- package/src/lib/select/select.element.ts +121 -0
- package/src/lib/select/select.stories.ts +33 -0
- package/src/lib/select/select.test.ts +113 -0
- package/src/lib/tag/tag.element.ts +46 -0
- package/src/lib/tag/tag.stories.ts +31 -0
- package/src/lib/tag/tag.test.ts +15 -0
- package/src/lib.ts +13 -0
- package/target/lib/alert/alert-types.d.ts +7 -0
- package/target/lib/alert/alert-types.js +25 -0
- package/target/lib/alert/alert-types.js.map +1 -0
- package/target/lib/alert/alert.element.d.ts +11 -0
- package/target/lib/alert/alert.element.js +124 -0
- package/target/lib/alert/alert.element.js.map +1 -0
- package/target/lib/alert/alert.stories.d.ts +11 -0
- package/target/lib/alert/alert.stories.js +56 -0
- package/target/lib/alert/alert.stories.js.map +1 -0
- package/target/lib/alert/alert.test.d.ts +1 -0
- package/target/lib/alert/alert.test.js +20 -0
- package/target/lib/alert/alert.test.js.map +1 -0
- package/target/lib/button/button.element.d.ts +17 -0
- package/target/lib/button/button.element.js +259 -0
- package/target/lib/button/button.element.js.map +1 -0
- package/target/lib/button/button.stories.d.ts +12 -0
- package/target/lib/button/button.stories.js +25 -0
- package/target/lib/button/button.stories.js.map +1 -0
- package/target/lib/button/button.test.d.ts +1 -0
- package/target/lib/button/button.test.js +14 -0
- package/target/lib/button/button.test.js.map +1 -0
- package/target/lib/checkbox/checkbox.element.d.ts +16 -0
- package/target/lib/checkbox/checkbox.element.js +205 -0
- package/target/lib/checkbox/checkbox.element.js.map +1 -0
- package/target/lib/checkbox/checkbox.stories.d.ts +31 -0
- package/target/lib/checkbox/checkbox.stories.js +46 -0
- package/target/lib/checkbox/checkbox.stories.js.map +1 -0
- package/target/lib/checkbox/checkbox.test.d.ts +1 -0
- package/target/lib/checkbox/checkbox.test.js +38 -0
- package/target/lib/checkbox/checkbox.test.js.map +1 -0
- package/target/lib/config/config.element.d.ts +8 -0
- package/target/lib/config/config.element.js +57 -0
- package/target/lib/config/config.element.js.map +1 -0
- package/target/lib/config/config.test.d.ts +1 -0
- package/target/lib/config/config.test.js +11 -0
- package/target/lib/config/config.test.js.map +1 -0
- package/target/lib/define.d.ts +14 -0
- package/target/lib/define.js +15 -0
- package/target/lib/define.js.map +1 -0
- package/target/lib/description/description.element.d.ts +7 -0
- package/target/lib/description/description.element.js +34 -0
- package/target/lib/description/description.element.js.map +1 -0
- package/target/lib/description/description.test.d.ts +1 -0
- package/target/lib/description/description.test.js +11 -0
- package/target/lib/description/description.test.js.map +1 -0
- package/target/lib/file-input/file-input-preview.element.d.ts +11 -0
- package/target/lib/file-input/file-input-preview.element.js +136 -0
- package/target/lib/file-input/file-input-preview.element.js.map +1 -0
- package/target/lib/file-input/file-input-preview.test.d.ts +2 -0
- package/target/lib/file-input/file-input-preview.test.js +67 -0
- package/target/lib/file-input/file-input-preview.test.js.map +1 -0
- package/target/lib/file-input/file-input.element.d.ts +18 -0
- package/target/lib/file-input/file-input.element.js +180 -0
- package/target/lib/file-input/file-input.element.js.map +1 -0
- package/target/lib/file-input/file-input.stories.d.ts +12 -0
- package/target/lib/file-input/file-input.stories.js +36 -0
- package/target/lib/file-input/file-input.stories.js.map +1 -0
- package/target/lib/file-input/file-input.test.d.ts +1 -0
- package/target/lib/file-input/file-input.test.js +37 -0
- package/target/lib/file-input/file-input.test.js.map +1 -0
- package/target/lib/icon/icon-types.d.ts +2 -0
- package/target/lib/icon/icon-types.js +262 -0
- package/target/lib/icon/icon-types.js.map +1 -0
- package/target/lib/icon/icon.element.d.ts +12 -0
- package/target/lib/icon/icon.element.js +84 -0
- package/target/lib/icon/icon.element.js.map +1 -0
- package/target/lib/icon/icon.stories.d.ts +12 -0
- package/target/lib/icon/icon.stories.js +39 -0
- package/target/lib/icon/icon.stories.js.map +1 -0
- package/target/lib/input/input.element.d.ts +19 -0
- package/target/lib/input/input.element.js +166 -0
- package/target/lib/input/input.element.js.map +1 -0
- package/target/lib/input/input.stories.d.ts +12 -0
- package/target/lib/input/input.stories.js +23 -0
- package/target/lib/input/input.stories.js.map +1 -0
- package/target/lib/input/input.test.d.ts +1 -0
- package/target/lib/input/input.test.js +38 -0
- package/target/lib/input/input.test.js.map +1 -0
- package/target/lib/input-mask/format.d.ts +15 -0
- package/target/lib/input-mask/format.js +47 -0
- package/target/lib/input-mask/format.js.map +1 -0
- package/target/lib/input-mask/input-mask.element.d.ts +12 -0
- package/target/lib/input-mask/input-mask.element.js +111 -0
- package/target/lib/input-mask/input-mask.element.js.map +1 -0
- package/target/lib/input-mask/input-mask.stories.d.ts +14 -0
- package/target/lib/input-mask/input-mask.stories.js +31 -0
- package/target/lib/input-mask/input-mask.stories.js.map +1 -0
- package/target/lib/input-mask/input-mask.test.d.ts +2 -0
- package/target/lib/input-mask/input-mask.test.js +85 -0
- package/target/lib/input-mask/input-mask.test.js.map +1 -0
- package/target/lib/input-mask/maskable.element.d.ts +5 -0
- package/target/lib/input-mask/maskable.element.js +2 -0
- package/target/lib/input-mask/maskable.element.js.map +1 -0
- package/target/lib/link/link.element.d.ts +13 -0
- package/target/lib/link/link.element.js +98 -0
- package/target/lib/link/link.element.js.map +1 -0
- package/target/lib/link/link.stories.d.ts +16 -0
- package/target/lib/link/link.stories.js +23 -0
- package/target/lib/link/link.stories.js.map +1 -0
- package/target/lib/radio/radio-option.element.d.ts +13 -0
- package/target/lib/radio/radio-option.element.js +63 -0
- package/target/lib/radio/radio-option.element.js.map +1 -0
- package/target/lib/radio/radio-option.test.d.ts +2 -0
- package/target/lib/radio/radio-option.test.js +15 -0
- package/target/lib/radio/radio-option.test.js.map +1 -0
- package/target/lib/radio/radio.element.d.ts +18 -0
- package/target/lib/radio/radio.element.js +177 -0
- package/target/lib/radio/radio.element.js.map +1 -0
- package/target/lib/radio/radio.stories.d.ts +12 -0
- package/target/lib/radio/radio.stories.js +40 -0
- package/target/lib/radio/radio.stories.js.map +1 -0
- package/target/lib/radio/radio.test.d.ts +2 -0
- package/target/lib/radio/radio.test.js +147 -0
- package/target/lib/radio/radio.test.js.map +1 -0
- package/target/lib/select/select-option.element.d.ts +11 -0
- package/target/lib/select/select-option.element.js +58 -0
- package/target/lib/select/select-option.element.js.map +1 -0
- package/target/lib/select/select.element.d.ts +16 -0
- package/target/lib/select/select.element.js +144 -0
- package/target/lib/select/select.element.js.map +1 -0
- package/target/lib/select/select.stories.d.ts +12 -0
- package/target/lib/select/select.stories.js +26 -0
- package/target/lib/select/select.stories.js.map +1 -0
- package/target/lib/select/select.test.d.ts +2 -0
- package/target/lib/select/select.test.js +89 -0
- package/target/lib/select/select.test.js.map +1 -0
- package/target/lib/tag/tag.element.d.ts +10 -0
- package/target/lib/tag/tag.element.js +66 -0
- package/target/lib/tag/tag.element.js.map +1 -0
- package/target/lib/tag/tag.stories.d.ts +19 -0
- package/target/lib/tag/tag.stories.js +25 -0
- package/target/lib/tag/tag.stories.js.map +1 -0
- package/target/lib/tag/tag.test.d.ts +1 -0
- package/target/lib/tag/tag.test.js +11 -0
- package/target/lib/tag/tag.test.js.map +1 -0
- package/target/lib.d.ts +13 -0
- package/target/lib.js +14 -0
- package/target/lib.js.map +1 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import "./file-input-preview.element.js";
|
|
2
|
+
import "../link/link.element.js";
|
|
3
|
+
|
|
4
|
+
import { attr, css, element, html, listen, query } from "@joist/element";
|
|
5
|
+
import { effect, observe } from "@joist/observable";
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
interface HTMLElementTagNameMap {
|
|
9
|
+
"usa-file-input": USAFileInputElement;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@element({
|
|
14
|
+
tagName: "usa-file-input",
|
|
15
|
+
shadowDom: [
|
|
16
|
+
css`
|
|
17
|
+
* {
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
:host {
|
|
22
|
+
display: block;
|
|
23
|
+
max-width: 30rem;
|
|
24
|
+
position: relative;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
label {
|
|
28
|
+
display: block;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
input {
|
|
32
|
+
cursor: pointer;
|
|
33
|
+
height: 100%;
|
|
34
|
+
left: 0;
|
|
35
|
+
margin: 0;
|
|
36
|
+
max-width: none;
|
|
37
|
+
position: absolute;
|
|
38
|
+
text-indent: -999em;
|
|
39
|
+
top: 0;
|
|
40
|
+
width: 100%;
|
|
41
|
+
z-index: 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
label slot {
|
|
45
|
+
font-size: 1.06rem;
|
|
46
|
+
line-height: 1.3;
|
|
47
|
+
display: block;
|
|
48
|
+
font-weight: 400;
|
|
49
|
+
margin-bottom: 0.5rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.box {
|
|
53
|
+
border: 1px dashed #adadad;
|
|
54
|
+
display: block;
|
|
55
|
+
font-size: 0.93rem;
|
|
56
|
+
position: relative;
|
|
57
|
+
text-align: center;
|
|
58
|
+
width: 100%;
|
|
59
|
+
max-width: 30rem;
|
|
60
|
+
padding: 2rem 1rem;
|
|
61
|
+
}
|
|
62
|
+
`,
|
|
63
|
+
html`
|
|
64
|
+
<label>
|
|
65
|
+
<slot></slot>
|
|
66
|
+
<input type="file" />
|
|
67
|
+
</label>
|
|
68
|
+
|
|
69
|
+
<div class="box">
|
|
70
|
+
<slot name="description">
|
|
71
|
+
Drag file here or <usa-link>choose from folder</usa-link>
|
|
72
|
+
</slot>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<usa-file-input-preview>
|
|
76
|
+
Selected file <usa-link>Change file</usa-link>
|
|
77
|
+
</usa-file-input-preview>
|
|
78
|
+
`,
|
|
79
|
+
],
|
|
80
|
+
})
|
|
81
|
+
export class USAFileInputElement extends HTMLElement {
|
|
82
|
+
static formAssociated = true;
|
|
83
|
+
|
|
84
|
+
@attr()
|
|
85
|
+
accessor name = "";
|
|
86
|
+
|
|
87
|
+
@attr()
|
|
88
|
+
accessor multiple = true;
|
|
89
|
+
|
|
90
|
+
@attr()
|
|
91
|
+
accessor accept = "";
|
|
92
|
+
|
|
93
|
+
@observe()
|
|
94
|
+
accessor files: FileList | null = null;
|
|
95
|
+
|
|
96
|
+
#internals = this.attachInternals();
|
|
97
|
+
#input = query("input");
|
|
98
|
+
#box = query(".box");
|
|
99
|
+
#preview = query("usa-file-input-preview");
|
|
100
|
+
|
|
101
|
+
@effect()
|
|
102
|
+
onChange() {
|
|
103
|
+
const input = this.#input();
|
|
104
|
+
|
|
105
|
+
if (this.files) {
|
|
106
|
+
input.files = this.files;
|
|
107
|
+
this.onInputChange();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
attributeChangedCallback() {
|
|
112
|
+
const input = this.#input();
|
|
113
|
+
input.name = this.name;
|
|
114
|
+
input.multiple = this.multiple;
|
|
115
|
+
input.accept = this.accept;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@listen("change")
|
|
119
|
+
onInputChange() {
|
|
120
|
+
const input = this.#input();
|
|
121
|
+
const box = this.#box();
|
|
122
|
+
const preview = this.#preview();
|
|
123
|
+
|
|
124
|
+
preview.files = input.files;
|
|
125
|
+
|
|
126
|
+
const formData = new FormData();
|
|
127
|
+
|
|
128
|
+
if (input.files) {
|
|
129
|
+
box.style.display = "none";
|
|
130
|
+
|
|
131
|
+
for (let file of input.files) {
|
|
132
|
+
formData.append(this.name, file);
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
box.style.display = "block";
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this.#internals.setFormValue(formData);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/web-components";
|
|
2
|
+
import { html } from "lit";
|
|
3
|
+
|
|
4
|
+
import type { USAFileInputElement } from "./file-input.element.js";
|
|
5
|
+
|
|
6
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
7
|
+
const meta = {
|
|
8
|
+
title: "usa-file-input",
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
render(args) {
|
|
11
|
+
function onSubmit(e: Event) {
|
|
12
|
+
e.preventDefault();
|
|
13
|
+
|
|
14
|
+
const data = new FormData(e.target as HTMLFormElement);
|
|
15
|
+
|
|
16
|
+
console.log(data.getAll("upload"));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return html`
|
|
20
|
+
<form @submit=${onSubmit}>
|
|
21
|
+
<usa-file-input name="upload">
|
|
22
|
+
Input accepts a single file
|
|
23
|
+
|
|
24
|
+
<div slot="description">
|
|
25
|
+
Drag file here or <usa-link>choose from folder</usa-link>
|
|
26
|
+
</div>
|
|
27
|
+
</usa-file-input>
|
|
28
|
+
|
|
29
|
+
<br />
|
|
30
|
+
|
|
31
|
+
<usa-button type="submit">SUBMIT</usa-button>
|
|
32
|
+
</form>
|
|
33
|
+
`;
|
|
34
|
+
},
|
|
35
|
+
argTypes: {},
|
|
36
|
+
args: {},
|
|
37
|
+
} satisfies Meta<USAFileInputElement>;
|
|
38
|
+
|
|
39
|
+
export default meta;
|
|
40
|
+
|
|
41
|
+
type Story = StoryObj<USAFileInputElement>;
|
|
42
|
+
|
|
43
|
+
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
|
44
|
+
export const Primary: Story = {
|
|
45
|
+
args: {},
|
|
46
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import "./file-input.element.js";
|
|
2
|
+
|
|
3
|
+
import { fixture, html, assert } from "@open-wc/testing";
|
|
4
|
+
|
|
5
|
+
import { USAFileInputElement } from "./file-input.element.js";
|
|
6
|
+
|
|
7
|
+
describe("usa-file-input", () => {
|
|
8
|
+
it("should be accessible", async () => {
|
|
9
|
+
const fileInput = await fixture<USAFileInputElement>(html`
|
|
10
|
+
<usa-file-input>Hello World</usa-file-input>
|
|
11
|
+
`);
|
|
12
|
+
|
|
13
|
+
return assert.isAccessible(fileInput);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should submit files with the form", async () => {
|
|
17
|
+
const data = new DataTransfer();
|
|
18
|
+
data.items.add(new File([], "first.txt"));
|
|
19
|
+
data.items.add(new File([], "second.txt"));
|
|
20
|
+
|
|
21
|
+
const form = await fixture<HTMLFormElement>(html`
|
|
22
|
+
<form>
|
|
23
|
+
<usa-file-input name="upload" .files=${data.files}>
|
|
24
|
+
Input accepts a single file
|
|
25
|
+
|
|
26
|
+
<div slot="description">
|
|
27
|
+
Drag file here or <usa-link>choose from folder</usa-link>
|
|
28
|
+
</div>
|
|
29
|
+
</usa-file-input>
|
|
30
|
+
|
|
31
|
+
<button>Submit</button>
|
|
32
|
+
</form>
|
|
33
|
+
`);
|
|
34
|
+
|
|
35
|
+
const formData = new FormData(form);
|
|
36
|
+
|
|
37
|
+
const fileNames = formData.getAll("upload").map((file) => {
|
|
38
|
+
if (file instanceof File) {
|
|
39
|
+
return file.name;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return "";
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
assert.deepEqual(fileNames, ["first.txt", "second.txt"]);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
export const ICON_TYPES = [
|
|
2
|
+
"accessibility_new",
|
|
3
|
+
"accessible_forward",
|
|
4
|
+
"account_balance",
|
|
5
|
+
"account_box",
|
|
6
|
+
"account_circle",
|
|
7
|
+
"add",
|
|
8
|
+
"add_circle",
|
|
9
|
+
"add_circle_outline",
|
|
10
|
+
"alarm",
|
|
11
|
+
"alternate_email",
|
|
12
|
+
"announcement",
|
|
13
|
+
"arrow_back",
|
|
14
|
+
"arrow_downward",
|
|
15
|
+
"arrow_drop_down",
|
|
16
|
+
"arrow_drop_up",
|
|
17
|
+
"arrow_forward",
|
|
18
|
+
"arrow_upward",
|
|
19
|
+
"api",
|
|
20
|
+
"assessment",
|
|
21
|
+
"attach_file",
|
|
22
|
+
"attach_money",
|
|
23
|
+
"autorenew",
|
|
24
|
+
"backpack",
|
|
25
|
+
"bathtub",
|
|
26
|
+
"bedding",
|
|
27
|
+
"bookmark",
|
|
28
|
+
"bug_report",
|
|
29
|
+
"build",
|
|
30
|
+
"calendar_today",
|
|
31
|
+
"campaign",
|
|
32
|
+
"camping",
|
|
33
|
+
"cancel",
|
|
34
|
+
"chat",
|
|
35
|
+
"check",
|
|
36
|
+
"check_box_outline_blank",
|
|
37
|
+
"check_circle",
|
|
38
|
+
"check_circle_outline",
|
|
39
|
+
"checkroom",
|
|
40
|
+
"clean_hands",
|
|
41
|
+
"clothes",
|
|
42
|
+
"close",
|
|
43
|
+
"closed_caption",
|
|
44
|
+
"cloud",
|
|
45
|
+
"code",
|
|
46
|
+
"comment",
|
|
47
|
+
"connect_without_contact",
|
|
48
|
+
"construction",
|
|
49
|
+
"construction_worker",
|
|
50
|
+
"contact_page",
|
|
51
|
+
"content_copy",
|
|
52
|
+
"coronavirus",
|
|
53
|
+
"credit_card",
|
|
54
|
+
"deck",
|
|
55
|
+
"delete",
|
|
56
|
+
"device_thermostat",
|
|
57
|
+
"directions",
|
|
58
|
+
"directions_bike",
|
|
59
|
+
"directions_bus",
|
|
60
|
+
"directions_car",
|
|
61
|
+
"directions_walk",
|
|
62
|
+
"do_not_disturb",
|
|
63
|
+
"do_not_touch",
|
|
64
|
+
"drag_handle",
|
|
65
|
+
"eco",
|
|
66
|
+
"edit",
|
|
67
|
+
"electrical_services",
|
|
68
|
+
"emoji_events",
|
|
69
|
+
"error",
|
|
70
|
+
"error_outline",
|
|
71
|
+
"event",
|
|
72
|
+
"expand_less",
|
|
73
|
+
"expand_more",
|
|
74
|
+
"facebook",
|
|
75
|
+
"fast_forward",
|
|
76
|
+
"fast_rewind",
|
|
77
|
+
"favorite",
|
|
78
|
+
"favorite_border",
|
|
79
|
+
"fax",
|
|
80
|
+
"file_download",
|
|
81
|
+
"file_present",
|
|
82
|
+
"file_upload",
|
|
83
|
+
"filter_alt",
|
|
84
|
+
"filter_list",
|
|
85
|
+
"fingerprint",
|
|
86
|
+
"first_page",
|
|
87
|
+
"flag",
|
|
88
|
+
"flickr",
|
|
89
|
+
"flight",
|
|
90
|
+
"flooding",
|
|
91
|
+
"folder",
|
|
92
|
+
"folder_open",
|
|
93
|
+
"format_quote",
|
|
94
|
+
"format_size",
|
|
95
|
+
"forum",
|
|
96
|
+
"github",
|
|
97
|
+
"grid_view",
|
|
98
|
+
"group_add",
|
|
99
|
+
"groups",
|
|
100
|
+
"hearing",
|
|
101
|
+
"help",
|
|
102
|
+
"help_outline",
|
|
103
|
+
"highlight_off",
|
|
104
|
+
"history",
|
|
105
|
+
"home",
|
|
106
|
+
"hospital",
|
|
107
|
+
"hotel",
|
|
108
|
+
"hourglass_empty",
|
|
109
|
+
"hurricane",
|
|
110
|
+
"identification",
|
|
111
|
+
"image",
|
|
112
|
+
"info",
|
|
113
|
+
"info_outline",
|
|
114
|
+
"insights",
|
|
115
|
+
"instagram",
|
|
116
|
+
"keyboard",
|
|
117
|
+
"label",
|
|
118
|
+
"language",
|
|
119
|
+
"last_page",
|
|
120
|
+
"launch",
|
|
121
|
+
"lightbulb",
|
|
122
|
+
"lightbulb_outline",
|
|
123
|
+
"link",
|
|
124
|
+
"link_off",
|
|
125
|
+
"linkedin",
|
|
126
|
+
"list",
|
|
127
|
+
"local_cafe",
|
|
128
|
+
"local_fire_department",
|
|
129
|
+
"local_gas_station",
|
|
130
|
+
"local_grocery_store",
|
|
131
|
+
"local_hospital",
|
|
132
|
+
"local_laundry_service",
|
|
133
|
+
"local_library",
|
|
134
|
+
"local_offer",
|
|
135
|
+
"local_parking",
|
|
136
|
+
"local_pharmacy",
|
|
137
|
+
"local_police",
|
|
138
|
+
"local_taxi",
|
|
139
|
+
"location_city",
|
|
140
|
+
"location_on",
|
|
141
|
+
"lock",
|
|
142
|
+
"lock_open",
|
|
143
|
+
"lock_outline",
|
|
144
|
+
"login",
|
|
145
|
+
"logout",
|
|
146
|
+
"loop",
|
|
147
|
+
"mail",
|
|
148
|
+
"mail_outline",
|
|
149
|
+
"map",
|
|
150
|
+
"masks",
|
|
151
|
+
"medical_services",
|
|
152
|
+
"menu",
|
|
153
|
+
"military_tech",
|
|
154
|
+
"more_horiz",
|
|
155
|
+
"more_vert",
|
|
156
|
+
"my_location",
|
|
157
|
+
"navigate_before",
|
|
158
|
+
"navigate_next",
|
|
159
|
+
"navigate_far_before",
|
|
160
|
+
"navigate_far_next",
|
|
161
|
+
"near_me",
|
|
162
|
+
"notifications",
|
|
163
|
+
"notifications_active",
|
|
164
|
+
"notifications_none",
|
|
165
|
+
"notifications_off",
|
|
166
|
+
"park",
|
|
167
|
+
"people",
|
|
168
|
+
"person",
|
|
169
|
+
"pets",
|
|
170
|
+
"phone",
|
|
171
|
+
"photo_camera",
|
|
172
|
+
"print",
|
|
173
|
+
"priority_high",
|
|
174
|
+
"public",
|
|
175
|
+
"push_pin",
|
|
176
|
+
"radio_button_unchecked",
|
|
177
|
+
"rain",
|
|
178
|
+
"reduce_capacity",
|
|
179
|
+
"remove",
|
|
180
|
+
"remove_circle",
|
|
181
|
+
"report",
|
|
182
|
+
"restaurant",
|
|
183
|
+
"rss_feed",
|
|
184
|
+
"safety_divider",
|
|
185
|
+
"sanitizer",
|
|
186
|
+
"severe_weather",
|
|
187
|
+
"save_alt",
|
|
188
|
+
"schedule",
|
|
189
|
+
"school",
|
|
190
|
+
"science",
|
|
191
|
+
"search",
|
|
192
|
+
"security",
|
|
193
|
+
"send",
|
|
194
|
+
"sentiment_dissatisfied",
|
|
195
|
+
"sentiment_neutral",
|
|
196
|
+
"sentiment_satisfied",
|
|
197
|
+
"sentiment_satisfied_alt",
|
|
198
|
+
"sentiment_very_dissatisfied",
|
|
199
|
+
"settings",
|
|
200
|
+
"share",
|
|
201
|
+
"shield",
|
|
202
|
+
"shopping_basket",
|
|
203
|
+
"snow",
|
|
204
|
+
"soap",
|
|
205
|
+
"social_distance",
|
|
206
|
+
"sort_arrow",
|
|
207
|
+
"spellcheck",
|
|
208
|
+
"star",
|
|
209
|
+
"star_half",
|
|
210
|
+
"star_outline",
|
|
211
|
+
"store",
|
|
212
|
+
"support",
|
|
213
|
+
"support_agent",
|
|
214
|
+
"text_fields",
|
|
215
|
+
"thumb_down_alt",
|
|
216
|
+
"thumb_up_alt",
|
|
217
|
+
"timer",
|
|
218
|
+
"toggle_off",
|
|
219
|
+
"toggle_on",
|
|
220
|
+
"topic",
|
|
221
|
+
"tornado",
|
|
222
|
+
"translate",
|
|
223
|
+
"trending_down",
|
|
224
|
+
"trending_up",
|
|
225
|
+
"twitter",
|
|
226
|
+
"undo",
|
|
227
|
+
"unfold_less",
|
|
228
|
+
"unfold_more",
|
|
229
|
+
"update",
|
|
230
|
+
"upload_file",
|
|
231
|
+
"verified",
|
|
232
|
+
"verified_user",
|
|
233
|
+
"visibility",
|
|
234
|
+
"visibility_off",
|
|
235
|
+
"volume_off",
|
|
236
|
+
"warning",
|
|
237
|
+
"wash",
|
|
238
|
+
"wifi",
|
|
239
|
+
"work",
|
|
240
|
+
"x",
|
|
241
|
+
"youtube",
|
|
242
|
+
"zoom_in",
|
|
243
|
+
"zoom_out_map",
|
|
244
|
+
"zoom_out",
|
|
245
|
+
"visibility",
|
|
246
|
+
"home",
|
|
247
|
+
"print",
|
|
248
|
+
"search",
|
|
249
|
+
"check_circle",
|
|
250
|
+
"warning",
|
|
251
|
+
"info",
|
|
252
|
+
"cancel",
|
|
253
|
+
"check_circle",
|
|
254
|
+
"warning",
|
|
255
|
+
"info",
|
|
256
|
+
"cancel",
|
|
257
|
+
"help",
|
|
258
|
+
"people",
|
|
259
|
+
"mail",
|
|
260
|
+
"support",
|
|
261
|
+
] as const;
|
|
262
|
+
|
|
263
|
+
export type USAIcon = (typeof ICON_TYPES)[number];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { attr, css, element, html, query } from "@joist/element";
|
|
2
|
+
import { inject, injectable } from "@joist/di";
|
|
3
|
+
|
|
4
|
+
import { USAIcon } from "./icon-types.js";
|
|
5
|
+
import { USAConfig } from "../config/config.element.js";
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
interface HTMLElementTagNameMap {
|
|
9
|
+
"usa-icon": USAIconElement;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@element({
|
|
14
|
+
tagName: "usa-icon",
|
|
15
|
+
shadowDom: [
|
|
16
|
+
css`
|
|
17
|
+
:host {
|
|
18
|
+
display: inline-block;
|
|
19
|
+
height: 2rem;
|
|
20
|
+
position: relative;
|
|
21
|
+
width: 2rem;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
svg {
|
|
25
|
+
fill: currentColor;
|
|
26
|
+
height: 100%;
|
|
27
|
+
width: 100%;
|
|
28
|
+
}
|
|
29
|
+
`,
|
|
30
|
+
html`
|
|
31
|
+
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img">
|
|
32
|
+
<use></use>
|
|
33
|
+
</svg>
|
|
34
|
+
`,
|
|
35
|
+
],
|
|
36
|
+
})
|
|
37
|
+
@injectable()
|
|
38
|
+
export class USAIconElement extends HTMLElement {
|
|
39
|
+
@attr()
|
|
40
|
+
accessor icon: USAIcon = "accessibility_new";
|
|
41
|
+
|
|
42
|
+
#use = query("use");
|
|
43
|
+
#config = inject(USAConfig);
|
|
44
|
+
#connected = false;
|
|
45
|
+
|
|
46
|
+
connectedCallback() {
|
|
47
|
+
this.#connected = true;
|
|
48
|
+
this.#updateIcon();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
attributeChangedCallback() {
|
|
52
|
+
if (this.#connected) {
|
|
53
|
+
this.#updateIcon();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#updateIcon() {
|
|
58
|
+
const config = this.#config();
|
|
59
|
+
const use = this.#use();
|
|
60
|
+
|
|
61
|
+
if (this.icon !== use.getAttribute("href")) {
|
|
62
|
+
use.setAttribute("href", `${config.spriteSheet}#${this.icon}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/web-components";
|
|
2
|
+
import { html } from "lit";
|
|
3
|
+
|
|
4
|
+
import type { USAIconElement } from "./icon.element.js";
|
|
5
|
+
import { ICON_TYPES } from "./icon-types.js";
|
|
6
|
+
|
|
7
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "usa-icon",
|
|
10
|
+
tags: [],
|
|
11
|
+
render(args) {
|
|
12
|
+
return html`<usa-icon icon=${args.icon}></usa-icon>`;
|
|
13
|
+
},
|
|
14
|
+
argTypes: {},
|
|
15
|
+
args: {},
|
|
16
|
+
} satisfies Meta<USAIconElement>;
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
|
|
20
|
+
type Story = StoryObj<USAIconElement>;
|
|
21
|
+
|
|
22
|
+
export const AllIcons: Story = {
|
|
23
|
+
render() {
|
|
24
|
+
async function copyIcon(icon: string) {
|
|
25
|
+
try {
|
|
26
|
+
await navigator.clipboard.writeText(
|
|
27
|
+
`<usa-icon icon=${icon}></usa-icon>`
|
|
28
|
+
);
|
|
29
|
+
alert(`copied markup for ${icon}`);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.error("Failed to copy: ", err);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return html`<div style="display: flex; flex-wrap: wrap; gap: .75rem;">
|
|
36
|
+
${html`${ICON_TYPES.map(
|
|
37
|
+
(icon) => html`
|
|
38
|
+
<button
|
|
39
|
+
@click=${() => copyIcon(icon)}
|
|
40
|
+
style="padding: .5rem 1rem .5rem .5rem; cursor: pointer; background: #fff; border-radius: 4px; gap: .5rem; display: flex; align-items: center"
|
|
41
|
+
>
|
|
42
|
+
<usa-icon icon=${icon}></usa-icon>
|
|
43
|
+
|
|
44
|
+
${icon}
|
|
45
|
+
</button>
|
|
46
|
+
`
|
|
47
|
+
)}`}
|
|
48
|
+
</div>`;
|
|
49
|
+
},
|
|
50
|
+
};
|