@noctuatech/uswds 1.3.1 → 1.3.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/package.json +6 -6
- package/src/lib/accordion/accordion.element.ts +18 -26
- package/src/lib/alert/alert.element.ts +21 -20
- package/src/lib/alert/alert.stories.ts +10 -15
- package/src/lib/file-input/file-input.element.ts +36 -31
- package/src/lib/icon/icon.element.ts +37 -27
- package/src/lib/input/input.element.ts +30 -39
- package/src/lib/input/input.test.ts +14 -16
- package/src/lib/input-mask/input-mask.element.ts +13 -13
- package/src/lib/input-mask/input-mask.stories.ts +7 -12
- package/src/lib/input-mask/input-mask.test.ts +45 -50
- package/src/lib/services/icon.service.test.ts +14 -14
- package/src/lib/services/icon.service.ts +18 -17
- package/src/lib/textarea/textarea.element.ts +14 -18
- package/target/lib/accordion/accordion.element.d.ts +4 -3
- package/target/lib/accordion/accordion.element.js +20 -12
- package/target/lib/accordion/accordion.element.js.map +1 -1
- package/target/lib/alert/alert.element.d.ts +4 -4
- package/target/lib/alert/alert.element.js +20 -12
- package/target/lib/alert/alert.element.js.map +1 -1
- package/target/lib/alert/alert.stories.d.ts +2 -2
- package/target/lib/alert/alert.stories.js +3 -3
- package/target/lib/alert/alert.stories.js.map +1 -1
- package/target/lib/file-input/file-input.element.d.ts +0 -1
- package/target/lib/file-input/file-input.element.js +6 -14
- package/target/lib/file-input/file-input.element.js.map +1 -1
- package/target/lib/icon/icon.element.d.ts +4 -4
- package/target/lib/icon/icon.element.js +35 -25
- package/target/lib/icon/icon.element.js.map +1 -1
- package/target/lib/input/input.element.d.ts +5 -5
- package/target/lib/input/input.element.js +20 -22
- package/target/lib/input/input.element.js.map +1 -1
- package/target/lib/input/input.test.d.ts +1 -1
- package/target/lib/input/input.test.js +13 -13
- package/target/lib/input/input.test.js.map +1 -1
- package/target/lib/input-mask/input-mask.element.d.ts +1 -1
- package/target/lib/input-mask/input-mask.element.js +11 -11
- package/target/lib/input-mask/input-mask.element.js.map +1 -1
- package/target/lib/input-mask/input-mask.stories.d.ts +2 -2
- package/target/lib/input-mask/input-mask.stories.js +5 -5
- package/target/lib/input-mask/input-mask.stories.js.map +1 -1
- package/target/lib/input-mask/input-mask.test.d.ts +2 -2
- package/target/lib/input-mask/input-mask.test.js +43 -43
- package/target/lib/input-mask/input-mask.test.js.map +1 -1
- package/target/lib/services/icon.service.d.ts +2 -1
- package/target/lib/services/icon.service.js +15 -15
- package/target/lib/services/icon.service.js.map +1 -1
- package/target/lib/services/icon.service.test.js +14 -14
- package/target/lib/services/icon.service.test.js.map +1 -1
- package/target/lib/textarea/textarea.element.d.ts +1 -1
- package/target/lib/textarea/textarea.element.js +10 -10
- package/target/lib/textarea/textarea.element.js.map +1 -1
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import './input.element.js';
|
|
2
2
|
|
|
3
|
-
import { assert, fixture, html } from
|
|
4
|
-
import { userEvent } from
|
|
3
|
+
import { assert, fixture, html } from '@open-wc/testing';
|
|
4
|
+
import { userEvent } from '@testing-library/user-event';
|
|
5
5
|
|
|
6
|
-
describe(
|
|
7
|
-
it(
|
|
8
|
-
const form = await fixture<HTMLFormElement>(html`
|
|
9
|
-
<usa-input name="fname" value="Foo">Hello World</usa-input>
|
|
10
|
-
`);
|
|
6
|
+
describe('usa-input', () => {
|
|
7
|
+
it('should be accessible', async () => {
|
|
8
|
+
const form = await fixture<HTMLFormElement>(html` <usa-input name="fname" value="Foo">Hello World</usa-input> `);
|
|
11
9
|
|
|
12
10
|
return assert.isAccessible(form);
|
|
13
11
|
});
|
|
14
12
|
|
|
15
|
-
it(
|
|
13
|
+
it('should submit form with default values', async () => {
|
|
16
14
|
const form = await fixture<HTMLFormElement>(html`
|
|
17
15
|
<form>
|
|
18
16
|
<usa-input name="fname" value="Foo">Hello World</usa-input>
|
|
@@ -23,10 +21,10 @@ describe("usa-input", () => {
|
|
|
23
21
|
|
|
24
22
|
const value = new FormData(form);
|
|
25
23
|
|
|
26
|
-
assert.equal(value.get(
|
|
24
|
+
assert.equal(value.get('fname'), 'Foo');
|
|
27
25
|
});
|
|
28
26
|
|
|
29
|
-
it(
|
|
27
|
+
it('should update form value as input value changed', async () => {
|
|
30
28
|
const form = await fixture<HTMLFormElement>(html`
|
|
31
29
|
<form>
|
|
32
30
|
<usa-input name="fname">Hello World</usa-input>
|
|
@@ -35,19 +33,19 @@ describe("usa-input", () => {
|
|
|
35
33
|
</form>
|
|
36
34
|
`);
|
|
37
35
|
|
|
38
|
-
const input = form.querySelector(
|
|
39
|
-
const nativeInput = input?.shadowRoot?.querySelector(
|
|
36
|
+
const input = form.querySelector('usa-input');
|
|
37
|
+
const nativeInput = input?.shadowRoot?.querySelector('input');
|
|
40
38
|
|
|
41
39
|
if (nativeInput) {
|
|
42
|
-
await userEvent.type(nativeInput,
|
|
40
|
+
await userEvent.type(nativeInput, 'Bar');
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
const value = new FormData(form);
|
|
46
44
|
|
|
47
|
-
assert.equal(value.get(
|
|
45
|
+
assert.equal(value.get('fname'), 'Bar');
|
|
48
46
|
});
|
|
49
47
|
|
|
50
|
-
it(
|
|
48
|
+
it('should not submit when not valid', async () => {
|
|
51
49
|
const form = await fixture<HTMLFormElement>(html`
|
|
52
50
|
<form>
|
|
53
51
|
<usa-input name="fname" required>Hello World</usa-input>
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { attr, css, element, html, listen, queryAll } from
|
|
1
|
+
import { attr, css, element, html, listen, queryAll } from '@joist/element';
|
|
2
2
|
|
|
3
|
-
import { PATTERN_CHARS, type PatternChar, REG_EXPS, format } from
|
|
4
|
-
import type { MaskableElement } from
|
|
3
|
+
import { PATTERN_CHARS, type PatternChar, REG_EXPS, format } from './format.js';
|
|
4
|
+
import type { MaskableElement } from './maskable.element.js';
|
|
5
5
|
|
|
6
6
|
declare global {
|
|
7
7
|
interface HTMLElementTagNameMap {
|
|
8
|
-
|
|
8
|
+
'usa-input-mask': USAInputMaskElement;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
@element({
|
|
13
|
-
tagName:
|
|
13
|
+
tagName: 'usa-input-mask',
|
|
14
14
|
shadowDom: [
|
|
15
15
|
css`
|
|
16
16
|
:host {
|
|
@@ -22,13 +22,13 @@ declare global {
|
|
|
22
22
|
})
|
|
23
23
|
export class USAInputMaskElement extends HTMLElement {
|
|
24
24
|
@attr()
|
|
25
|
-
accessor mask =
|
|
25
|
+
accessor mask = '';
|
|
26
26
|
|
|
27
|
-
#maskables = queryAll<MaskableElement>(
|
|
27
|
+
#maskables = queryAll<MaskableElement>('[mask]', this);
|
|
28
28
|
|
|
29
29
|
connectedCallback() {
|
|
30
30
|
for (const input of this.#maskables()) {
|
|
31
|
-
const { formatted } = format(input.value, this.#getMaskFor(input));
|
|
31
|
+
const { formatted } = format(input.value || input.getAttribute('value') || '', this.#getMaskFor(input));
|
|
32
32
|
|
|
33
33
|
if (formatted) {
|
|
34
34
|
input.value = formatted;
|
|
@@ -36,7 +36,7 @@ export class USAInputMaskElement extends HTMLElement {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
@listen(
|
|
39
|
+
@listen('input')
|
|
40
40
|
onInput(e: Event) {
|
|
41
41
|
const input = e.target as MaskableElement;
|
|
42
42
|
const selectionStart = input.selectionStart || 0;
|
|
@@ -60,7 +60,7 @@ export class USAInputMaskElement extends HTMLElement {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
@listen(
|
|
63
|
+
@listen('keydown')
|
|
64
64
|
onKeyDown(e: KeyboardEvent) {
|
|
65
65
|
const input = e.target as MaskableElement;
|
|
66
66
|
const mask = this.#getMaskFor(input);
|
|
@@ -72,12 +72,12 @@ export class USAInputMaskElement extends HTMLElement {
|
|
|
72
72
|
if (input.value.length >= mask.length) {
|
|
73
73
|
// prevent default once value is the same as the mask length
|
|
74
74
|
e.preventDefault();
|
|
75
|
-
} else if (patternChar ===
|
|
75
|
+
} else if (patternChar === '9') {
|
|
76
76
|
if (!REG_EXPS.Numbers.test(e.key)) {
|
|
77
77
|
// if pattern char specifies number and is not
|
|
78
78
|
e.preventDefault();
|
|
79
79
|
}
|
|
80
|
-
} else if (patternChar ===
|
|
80
|
+
} else if (patternChar === 'A') {
|
|
81
81
|
if (!REG_EXPS.Letters.test(e.key)) {
|
|
82
82
|
// if pattern char specifies letter and is not
|
|
83
83
|
e.preventDefault();
|
|
@@ -87,6 +87,6 @@ export class USAInputMaskElement extends HTMLElement {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
#getMaskFor(input: MaskableElement) {
|
|
90
|
-
return this.mask || input.getAttribute(
|
|
90
|
+
return this.mask || input.getAttribute('mask') || '';
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { html } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/web-components';
|
|
2
|
+
import { html } from 'lit';
|
|
3
3
|
|
|
4
|
-
import type { USAInputMaskElement } from
|
|
4
|
+
import type { USAInputMaskElement } from './input-mask.element.js';
|
|
5
5
|
|
|
6
6
|
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
7
7
|
const meta = {
|
|
8
|
-
title:
|
|
9
|
-
tags: [
|
|
8
|
+
title: 'input-mask',
|
|
9
|
+
tags: ['autodocs'],
|
|
10
10
|
render(args) {
|
|
11
11
|
return html`
|
|
12
12
|
<usa-input-mask>
|
|
13
|
-
<usa-input
|
|
14
|
-
name="phone"
|
|
15
|
-
placeholder=${args.mask}
|
|
16
|
-
autocomplete="off"
|
|
17
|
-
mask=${args.mask}
|
|
18
|
-
>
|
|
13
|
+
<usa-input name="phone" placeholder=${args.mask} autocomplete="off" mask=${args.mask} value="1234567890">
|
|
19
14
|
Phone:
|
|
20
15
|
</usa-input>
|
|
21
16
|
</usa-input-mask>
|
|
@@ -23,7 +18,7 @@ const meta = {
|
|
|
23
18
|
},
|
|
24
19
|
argTypes: {},
|
|
25
20
|
args: {
|
|
26
|
-
mask:
|
|
21
|
+
mask: '(999) 999-9999',
|
|
27
22
|
},
|
|
28
23
|
} satisfies Meta<USAInputMaskElement>;
|
|
29
24
|
|
|
@@ -1,110 +1,105 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import './input-mask.element.js';
|
|
2
|
+
import '../input/input.element.js';
|
|
3
3
|
|
|
4
|
-
import { assert, fixture, html } from
|
|
4
|
+
import { assert, fixture, html } from '@open-wc/testing';
|
|
5
5
|
|
|
6
|
-
import { format } from
|
|
7
|
-
import type { USAInputMaskElement } from
|
|
6
|
+
import { format } from './format.js';
|
|
7
|
+
import type { USAInputMaskElement } from './input-mask.element.js';
|
|
8
8
|
|
|
9
|
-
describe(
|
|
10
|
-
it(
|
|
11
|
-
assert.deepEqual(format(
|
|
12
|
-
raw:
|
|
13
|
-
formatted:
|
|
9
|
+
describe('format', () => {
|
|
10
|
+
it('should retrn the correct raw value', () => {
|
|
11
|
+
assert.deepEqual(format('(123) 456 7890', '(***) ***-****'), {
|
|
12
|
+
raw: '1234567890',
|
|
13
|
+
formatted: '(123) 456-7890',
|
|
14
14
|
});
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
it(
|
|
18
|
-
assert.deepEqual(format(
|
|
19
|
-
raw:
|
|
20
|
-
formatted:
|
|
17
|
+
it('should return a formatted phone number (***) ***-****', () => {
|
|
18
|
+
assert.deepEqual(format('1234567890', '(***) ***-****'), {
|
|
19
|
+
raw: '1234567890',
|
|
20
|
+
formatted: '(123) 456-7890',
|
|
21
21
|
});
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
it(
|
|
25
|
-
assert.deepEqual(format(
|
|
26
|
-
raw:
|
|
27
|
-
formatted:
|
|
24
|
+
it('should return a formatted phone number ***-***-****', () => {
|
|
25
|
+
assert.deepEqual(format('1234567890', '***-***-****'), {
|
|
26
|
+
raw: '1234567890',
|
|
27
|
+
formatted: '123-456-7890',
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
it(
|
|
32
|
-
assert.deepEqual(format(
|
|
33
|
-
raw:
|
|
34
|
-
formatted:
|
|
31
|
+
it('should only allow numbers', () => {
|
|
32
|
+
assert.deepEqual(format('304213abcd', '999-999-9999'), {
|
|
33
|
+
raw: '304213abcd',
|
|
34
|
+
formatted: '304-213-',
|
|
35
35
|
});
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
it(
|
|
39
|
-
assert.deepEqual(format(
|
|
40
|
-
raw:
|
|
41
|
-
formatted:
|
|
38
|
+
it('should only allow a mix of letters and numbers', () => {
|
|
39
|
+
assert.deepEqual(format('C94749', 'A-99999'), {
|
|
40
|
+
raw: 'C94749',
|
|
41
|
+
formatted: 'C-94749',
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
describe(
|
|
47
|
-
it(
|
|
46
|
+
describe('usa-input-mask', () => {
|
|
47
|
+
it('should format default value', async () => {
|
|
48
48
|
const el = await fixture<USAInputMaskElement>(html`
|
|
49
49
|
<usa-input-mask mask="(999) 999-9999">
|
|
50
50
|
<input name="phone" value="1234567890" mask />
|
|
51
51
|
</usa-input-mask>
|
|
52
52
|
`);
|
|
53
53
|
|
|
54
|
-
const input = el.querySelector(
|
|
54
|
+
const input = el.querySelector('input');
|
|
55
55
|
|
|
56
|
-
assert.equal(input?.value,
|
|
56
|
+
assert.equal(input?.value, '(123) 456-7890');
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
it(
|
|
59
|
+
it('should update value when on input event', async () => {
|
|
60
60
|
const el = await fixture<USAInputMaskElement>(html`
|
|
61
61
|
<usa-input-mask>
|
|
62
62
|
<input name="phone" mask="(999) 999-9999" />
|
|
63
63
|
</usa-input-mask>
|
|
64
64
|
`);
|
|
65
65
|
|
|
66
|
-
const input = el.querySelector(
|
|
66
|
+
const input = el.querySelector('input');
|
|
67
67
|
|
|
68
68
|
if (input) {
|
|
69
|
-
input.value =
|
|
70
|
-
input.dispatchEvent(new Event(
|
|
69
|
+
input.value = '8888888888';
|
|
70
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
assert.equal(input?.value, "(888) 888-8888");
|
|
72
|
+
assert.equal(input?.value, '(888) 888-8888');
|
|
74
73
|
});
|
|
75
74
|
});
|
|
76
75
|
|
|
77
|
-
describe(
|
|
78
|
-
it(
|
|
76
|
+
describe('usa-input-mask with usa-input', () => {
|
|
77
|
+
it('should format default value', async () => {
|
|
79
78
|
const el = await fixture<USAInputMaskElement>(html`
|
|
80
79
|
<usa-input-mask mask="(999) 999-9999">
|
|
81
80
|
<usa-input name="phone" value="1234567890" id="TEST" mask></usa-input>
|
|
82
81
|
</usa-input-mask>
|
|
83
82
|
`);
|
|
84
83
|
|
|
85
|
-
const input = el.querySelector(
|
|
84
|
+
const input = el.querySelector('usa-input');
|
|
86
85
|
|
|
87
|
-
assert.equal(input?.value,
|
|
86
|
+
assert.equal(input?.value, '(123) 456-7890');
|
|
88
87
|
});
|
|
89
88
|
|
|
90
|
-
it(
|
|
89
|
+
it('should update value when on input event', async () => {
|
|
91
90
|
const el = await fixture<USAInputMaskElement>(html`
|
|
92
91
|
<usa-input-mask>
|
|
93
|
-
<usa-input
|
|
94
|
-
name="phone"
|
|
95
|
-
value="1234567890"
|
|
96
|
-
mask="(999) 999-9999"
|
|
97
|
-
></usa-input>
|
|
92
|
+
<usa-input name="phone" value="1234567890" mask="(999) 999-9999"></usa-input>
|
|
98
93
|
</usa-input-mask>
|
|
99
94
|
`);
|
|
100
95
|
|
|
101
|
-
const input = el.querySelector(
|
|
96
|
+
const input = el.querySelector('usa-input');
|
|
102
97
|
|
|
103
98
|
if (input) {
|
|
104
|
-
input.value =
|
|
105
|
-
input.dispatchEvent(new Event(
|
|
99
|
+
input.value = '8888888888';
|
|
100
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
106
101
|
}
|
|
107
102
|
|
|
108
|
-
assert.equal(input?.value,
|
|
103
|
+
assert.equal(input?.value, '(888) 888-8888');
|
|
109
104
|
});
|
|
110
105
|
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Injector } from
|
|
2
|
-
import { assert } from
|
|
1
|
+
import { Injector } from '@joist/di';
|
|
2
|
+
import { assert } from '@open-wc/testing';
|
|
3
3
|
|
|
4
|
-
import { HttpService } from
|
|
5
|
-
import { IconService } from
|
|
4
|
+
import { HttpService } from './http.service.js';
|
|
5
|
+
import { IconService } from './icon.service.js';
|
|
6
6
|
|
|
7
|
-
describe(
|
|
8
|
-
it(
|
|
7
|
+
describe('IconService', () => {
|
|
8
|
+
it('should fetch icon if not in cache', async () => {
|
|
9
9
|
let callCount = 0;
|
|
10
10
|
|
|
11
11
|
const app = new Injector({
|
|
@@ -16,7 +16,7 @@ describe("IconService", () => {
|
|
|
16
16
|
use: class extends HttpService {
|
|
17
17
|
async fetch(): Promise<Response> {
|
|
18
18
|
callCount++;
|
|
19
|
-
return new Response(
|
|
19
|
+
return new Response('<svg></svg>');
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
},
|
|
@@ -26,13 +26,13 @@ describe("IconService", () => {
|
|
|
26
26
|
|
|
27
27
|
const icon = app.inject(IconService);
|
|
28
28
|
|
|
29
|
-
const res = await icon.getIcon(
|
|
29
|
+
const res = await icon.getIcon('test' as any);
|
|
30
30
|
|
|
31
|
-
assert.equal(res.nodeName,
|
|
31
|
+
assert.equal(res.nodeName, 'svg');
|
|
32
32
|
assert.equal(callCount, 1);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
it(
|
|
35
|
+
it('should not fetch new icon if the icon is found in the cache', async () => {
|
|
36
36
|
let callCount = 0;
|
|
37
37
|
|
|
38
38
|
const app = new Injector({
|
|
@@ -43,7 +43,7 @@ describe("IconService", () => {
|
|
|
43
43
|
use: class extends HttpService {
|
|
44
44
|
async fetch(): Promise<Response> {
|
|
45
45
|
callCount++;
|
|
46
|
-
return new Response(
|
|
46
|
+
return new Response('<svg></svg>');
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
},
|
|
@@ -53,11 +53,11 @@ describe("IconService", () => {
|
|
|
53
53
|
|
|
54
54
|
const icon = app.inject(IconService);
|
|
55
55
|
|
|
56
|
-
await icon.getIcon(
|
|
56
|
+
await icon.getIcon('accessibility_new');
|
|
57
57
|
|
|
58
|
-
const res = await icon.getIcon(
|
|
58
|
+
const res = await icon.getIcon('accessibility_new');
|
|
59
59
|
|
|
60
|
-
assert.equal(res.nodeName,
|
|
60
|
+
assert.equal(res.nodeName, 'svg');
|
|
61
61
|
assert.equal(callCount, 1);
|
|
62
62
|
});
|
|
63
63
|
});
|
|
@@ -1,52 +1,53 @@
|
|
|
1
|
-
import { inject, injectable } from
|
|
1
|
+
import { inject, injectable } from '@joist/di';
|
|
2
2
|
|
|
3
|
-
import { USAConfig } from
|
|
4
|
-
import { HttpService } from
|
|
3
|
+
import { USAConfig } from '../config/config.element.js';
|
|
4
|
+
import { HttpService } from './http.service.js';
|
|
5
|
+
import { USAIcon } from '../icon/icon-types.js';
|
|
5
6
|
|
|
6
7
|
@injectable()
|
|
7
8
|
export class IconService {
|
|
8
9
|
#config = inject(USAConfig);
|
|
9
10
|
#http = inject(HttpService);
|
|
10
|
-
#iconCache: Map<
|
|
11
|
+
#iconCache: Map<USAIcon, HTMLTemplateElement> = new Map();
|
|
11
12
|
|
|
12
|
-
async getIcon(icon:
|
|
13
|
+
async getIcon(icon: USAIcon, abortSignal?: AbortSignal): Promise<Node> {
|
|
13
14
|
const config = this.#config();
|
|
14
15
|
const http = this.#http();
|
|
15
16
|
|
|
16
17
|
const cached = this.#iconCache.get(icon);
|
|
17
18
|
|
|
18
19
|
if (cached) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
20
|
+
if (!cached.content.firstElementChild) {
|
|
21
|
+
throw Error('cached value is not valid');
|
|
22
|
+
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
});
|
|
24
|
+
return cached.content.firstElementChild.cloneNode(true);
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
const svg = http
|
|
29
|
-
.fetch(`${config.iconPath}${icon}.svg
|
|
28
|
+
.fetch(`${config.iconPath}${icon}.svg`, {
|
|
29
|
+
signal: abortSignal,
|
|
30
|
+
})
|
|
30
31
|
.then((res) => {
|
|
31
32
|
switch (res.status) {
|
|
32
33
|
case 200:
|
|
33
34
|
return res.text();
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
return
|
|
37
|
+
return '';
|
|
37
38
|
})
|
|
38
39
|
.then((res) => {
|
|
39
|
-
const template = document.createElement(
|
|
40
|
+
const template = document.createElement('template');
|
|
40
41
|
template.innerHTML = res;
|
|
41
42
|
|
|
43
|
+
this.#iconCache.set(icon, template);
|
|
44
|
+
|
|
42
45
|
return template;
|
|
43
46
|
});
|
|
44
47
|
|
|
45
|
-
this.#iconCache.set(icon, svg);
|
|
46
|
-
|
|
47
48
|
return svg.then((res) => {
|
|
48
49
|
if (!res.content.firstElementChild) {
|
|
49
|
-
throw Error(
|
|
50
|
+
throw Error('ICON is not valid');
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
return res.content.firstElementChild.cloneNode(true);
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { attr, css, element, html, listen, query, ready } from
|
|
2
|
-
import { effect, observe } from
|
|
1
|
+
import { attr, css, element, html, listen, query, ready } from '@joist/element';
|
|
2
|
+
import { effect, observe } from '@joist/observable';
|
|
3
3
|
|
|
4
4
|
declare global {
|
|
5
5
|
interface HTMLElementTagNameMap {
|
|
6
|
-
|
|
6
|
+
'usa-textarea': USATextareaElement;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
@element({
|
|
11
|
-
tagName:
|
|
11
|
+
tagName: 'usa-textarea',
|
|
12
12
|
shadowDom: [
|
|
13
13
|
css`
|
|
14
14
|
* {
|
|
@@ -34,7 +34,7 @@ declare global {
|
|
|
34
34
|
border-radius: 0;
|
|
35
35
|
color: #1b1b1b;
|
|
36
36
|
display: block;
|
|
37
|
-
padding: .5rem;
|
|
37
|
+
padding: 0.5rem;
|
|
38
38
|
border-width: 1px;
|
|
39
39
|
border-color: #5c5c5c;
|
|
40
40
|
border-style: solid;
|
|
@@ -62,7 +62,7 @@ declare global {
|
|
|
62
62
|
<label for="textarea" part="label">
|
|
63
63
|
<slot></slot>
|
|
64
64
|
</label>
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
<textarea id="textarea" part="textarea"></textarea>
|
|
67
67
|
`,
|
|
68
68
|
],
|
|
@@ -71,13 +71,13 @@ export class USATextareaElement extends HTMLElement {
|
|
|
71
71
|
static formAssociated = true;
|
|
72
72
|
|
|
73
73
|
@attr()
|
|
74
|
-
accessor name =
|
|
74
|
+
accessor name = '';
|
|
75
75
|
|
|
76
76
|
@attr()
|
|
77
|
-
accessor autocomplete: AutoFill =
|
|
77
|
+
accessor autocomplete: AutoFill = 'on';
|
|
78
78
|
|
|
79
79
|
@attr()
|
|
80
|
-
accessor placeholder =
|
|
80
|
+
accessor placeholder = '';
|
|
81
81
|
|
|
82
82
|
@attr()
|
|
83
83
|
accessor required = false;
|
|
@@ -86,10 +86,10 @@ export class USATextareaElement extends HTMLElement {
|
|
|
86
86
|
reflect: false,
|
|
87
87
|
})
|
|
88
88
|
@observe()
|
|
89
|
-
accessor value =
|
|
89
|
+
accessor value = '';
|
|
90
90
|
|
|
91
91
|
#internals = this.attachInternals();
|
|
92
|
-
#input = query(
|
|
92
|
+
#input = query('textarea');
|
|
93
93
|
|
|
94
94
|
@ready()
|
|
95
95
|
onReady() {
|
|
@@ -116,7 +116,7 @@ export class USATextareaElement extends HTMLElement {
|
|
|
116
116
|
this.#syncFormState();
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
@listen(
|
|
119
|
+
@listen('input')
|
|
120
120
|
onInputChange() {
|
|
121
121
|
this.value = this.#input().value;
|
|
122
122
|
}
|
|
@@ -124,15 +124,11 @@ export class USATextareaElement extends HTMLElement {
|
|
|
124
124
|
#syncFormState() {
|
|
125
125
|
const input = this.#input();
|
|
126
126
|
|
|
127
|
-
this.#internals.setFormValue(
|
|
127
|
+
this.#internals.setFormValue(this.value);
|
|
128
128
|
this.#internals.setValidity({});
|
|
129
129
|
|
|
130
130
|
if (input.validationMessage) {
|
|
131
|
-
this.#internals.setValidity(
|
|
132
|
-
{ customError: true },
|
|
133
|
-
input.validationMessage,
|
|
134
|
-
input,
|
|
135
|
-
);
|
|
131
|
+
this.#internals.setValidity({ customError: true }, input.validationMessage, input);
|
|
136
132
|
}
|
|
137
133
|
}
|
|
138
134
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { USAAccordionToggleEvent } from
|
|
1
|
+
import '@joist/templating/define.js';
|
|
2
|
+
import { USAAccordionToggleEvent } from './events.js';
|
|
3
3
|
declare global {
|
|
4
4
|
interface HTMLElementTagNameMap {
|
|
5
|
-
|
|
5
|
+
'usa-accordion': USAAccordionElement;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
export declare class USAAccordionElement extends HTMLElement {
|
|
9
9
|
accessor name: string;
|
|
10
10
|
accessor open: boolean;
|
|
11
|
+
accessor icon: 'add' | 'remove';
|
|
11
12
|
onClick(e: Event): void;
|
|
12
13
|
onAccordionToggle(e: USAAccordionToggleEvent): void;
|
|
13
14
|
}
|