accented 0.0.0-20250424114613 → 0.0.0-20250618181418
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/README.md +0 -209
- package/dist/accented.d.ts +2 -2
- package/dist/accented.d.ts.map +1 -1
- package/dist/accented.js +24 -20
- package/dist/accented.js.map +1 -1
- package/dist/common/tokens.d.ts +2 -0
- package/dist/common/tokens.d.ts.map +1 -0
- package/dist/common/tokens.js +2 -0
- package/dist/common/tokens.js.map +1 -0
- package/dist/dom-updater.d.ts +1 -1
- package/dist/dom-updater.d.ts.map +1 -1
- package/dist/dom-updater.js +14 -13
- package/dist/dom-updater.js.map +1 -1
- package/dist/elements/accented-dialog.d.ts +2 -3
- package/dist/elements/accented-dialog.d.ts.map +1 -1
- package/dist/elements/accented-dialog.js +14 -8
- package/dist/elements/accented-dialog.js.map +1 -1
- package/dist/elements/accented-trigger.d.ts +3 -4
- package/dist/elements/accented-trigger.d.ts.map +1 -1
- package/dist/elements/accented-trigger.js +8 -10
- package/dist/elements/accented-trigger.js.map +1 -1
- package/dist/fullscreen-listener.d.ts +1 -1
- package/dist/fullscreen-listener.d.ts.map +1 -1
- package/dist/fullscreen-listener.js +3 -4
- package/dist/fullscreen-listener.js.map +1 -1
- package/dist/intersection-observer.d.ts +1 -1
- package/dist/intersection-observer.d.ts.map +1 -1
- package/dist/intersection-observer.js +12 -6
- package/dist/intersection-observer.js.map +1 -1
- package/dist/log-and-rethrow.d.ts +1 -1
- package/dist/log-and-rethrow.d.ts.map +1 -1
- package/dist/log-and-rethrow.js +2 -3
- package/dist/log-and-rethrow.js.map +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +2 -2
- package/dist/logger.js.map +1 -1
- package/dist/register-elements.d.ts +1 -1
- package/dist/register-elements.d.ts.map +1 -1
- package/dist/register-elements.js +6 -7
- package/dist/register-elements.js.map +1 -1
- package/dist/resize-listener.d.ts +1 -1
- package/dist/resize-listener.d.ts.map +1 -1
- package/dist/resize-listener.js +3 -4
- package/dist/resize-listener.js.map +1 -1
- package/dist/scanner.d.ts +2 -2
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +25 -27
- package/dist/scanner.js.map +1 -1
- package/dist/scroll-listeners.d.ts +1 -1
- package/dist/scroll-listeners.d.ts.map +1 -1
- package/dist/scroll-listeners.js +3 -4
- package/dist/scroll-listeners.js.map +1 -1
- package/dist/state.d.ts +1 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +4 -5
- package/dist/state.js.map +1 -1
- package/dist/task-queue.d.ts +2 -2
- package/dist/task-queue.d.ts.map +1 -1
- package/dist/task-queue.js +1 -1
- package/dist/task-queue.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/are-elements-with-issues-equal.d.ts +2 -2
- package/dist/utils/are-elements-with-issues-equal.d.ts.map +1 -1
- package/dist/utils/are-elements-with-issues-equal.js +3 -3
- package/dist/utils/are-elements-with-issues-equal.js.map +1 -1
- package/dist/utils/are-issue-sets-equal.d.ts +2 -2
- package/dist/utils/are-issue-sets-equal.d.ts.map +1 -1
- package/dist/utils/are-issue-sets-equal.js +3 -3
- package/dist/utils/are-issue-sets-equal.js.map +1 -1
- package/dist/utils/containing-blocks.d.ts.map +1 -1
- package/dist/utils/containing-blocks.js +1 -1
- package/dist/utils/containing-blocks.js.map +1 -1
- package/dist/utils/contains.d.ts +1 -1
- package/dist/utils/contains.d.ts.map +1 -1
- package/dist/utils/contains.js +1 -1
- package/dist/utils/contains.js.map +1 -1
- package/dist/utils/deduplicate-nodes.js +0 -1
- package/dist/utils/deduplicate-nodes.js.map +1 -1
- package/dist/utils/deep-merge.d.ts +1 -1
- package/dist/utils/deep-merge.d.ts.map +1 -1
- package/dist/utils/deep-merge.js +6 -5
- package/dist/utils/deep-merge.js.map +1 -1
- package/dist/utils/dom-helpers.d.ts.map +1 -1
- package/dist/utils/dom-helpers.js +4 -2
- package/dist/utils/dom-helpers.js.map +1 -1
- package/dist/utils/ensure-non-empty.d.ts +1 -1
- package/dist/utils/ensure-non-empty.d.ts.map +1 -1
- package/dist/utils/ensure-non-empty.js +2 -2
- package/dist/utils/ensure-non-empty.js.map +1 -1
- package/dist/utils/get-element-html.d.ts +1 -1
- package/dist/utils/get-element-html.d.ts.map +1 -1
- package/dist/utils/get-element-html.js +4 -2
- package/dist/utils/get-element-html.js.map +1 -1
- package/dist/utils/get-element-position.d.ts +2 -2
- package/dist/utils/get-element-position.d.ts.map +1 -1
- package/dist/utils/get-element-position.js +21 -25
- package/dist/utils/get-element-position.js.map +1 -1
- package/dist/utils/get-parent.d.ts +1 -1
- package/dist/utils/get-parent.d.ts.map +1 -1
- package/dist/utils/get-parent.js +1 -1
- package/dist/utils/get-parent.js.map +1 -1
- package/dist/utils/get-scan-context.d.ts +2 -2
- package/dist/utils/get-scan-context.d.ts.map +1 -1
- package/dist/utils/get-scan-context.js +9 -9
- package/dist/utils/get-scan-context.js.map +1 -1
- package/dist/utils/get-scrollable-ancestors.d.ts +1 -1
- package/dist/utils/get-scrollable-ancestors.d.ts.map +1 -1
- package/dist/utils/get-scrollable-ancestors.js +5 -5
- package/dist/utils/get-scrollable-ancestors.js.map +1 -1
- package/dist/utils/is-node-in-scan-context.d.ts +2 -2
- package/dist/utils/is-node-in-scan-context.d.ts.map +1 -1
- package/dist/utils/is-node-in-scan-context.js +5 -5
- package/dist/utils/is-node-in-scan-context.js.map +1 -1
- package/dist/utils/is-non-empty.d.ts +2 -0
- package/dist/utils/is-non-empty.d.ts.map +1 -0
- package/dist/utils/is-non-empty.js +4 -0
- package/dist/utils/is-non-empty.js.map +1 -0
- package/dist/utils/normalize-context.d.ts +2 -2
- package/dist/utils/normalize-context.d.ts.map +1 -1
- package/dist/utils/normalize-context.js +10 -8
- package/dist/utils/normalize-context.js.map +1 -1
- package/dist/utils/recalculate-positions.d.ts +1 -1
- package/dist/utils/recalculate-positions.d.ts.map +1 -1
- package/dist/utils/recalculate-positions.js +5 -5
- package/dist/utils/recalculate-positions.js.map +1 -1
- package/dist/utils/recalculate-scrollable-ancestors.d.ts +1 -1
- package/dist/utils/recalculate-scrollable-ancestors.d.ts.map +1 -1
- package/dist/utils/recalculate-scrollable-ancestors.js +4 -4
- package/dist/utils/recalculate-scrollable-ancestors.js.map +1 -1
- package/dist/utils/shadow-dom-aware-mutation-observer.d.ts +1 -1
- package/dist/utils/shadow-dom-aware-mutation-observer.d.ts.map +1 -1
- package/dist/utils/shadow-dom-aware-mutation-observer.js +19 -22
- package/dist/utils/shadow-dom-aware-mutation-observer.js.map +1 -1
- package/dist/utils/supports-anchor-positioning.d.ts +1 -1
- package/dist/utils/supports-anchor-positioning.d.ts.map +1 -1
- package/dist/utils/supports-anchor-positioning.js +1 -1
- package/dist/utils/supports-anchor-positioning.js.map +1 -1
- package/dist/utils/transform-violations.d.ts +2 -2
- package/dist/utils/transform-violations.d.ts.map +1 -1
- package/dist/utils/transform-violations.js +9 -9
- package/dist/utils/transform-violations.js.map +1 -1
- package/dist/utils/update-elements-with-issues.d.ts +3 -3
- package/dist/utils/update-elements-with-issues.d.ts.map +1 -1
- package/dist/utils/update-elements-with-issues.js +34 -29
- package/dist/utils/update-elements-with-issues.js.map +1 -1
- package/dist/validate-options.d.ts +2 -2
- package/dist/validate-options.d.ts.map +1 -1
- package/dist/validate-options.js +24 -23
- package/dist/validate-options.js.map +1 -1
- package/package.json +5 -3
- package/src/accented.test.ts +2 -2
- package/src/accented.ts +34 -26
- package/src/common/tokens.ts +1 -0
- package/src/dom-updater.ts +26 -19
- package/src/elements/accented-dialog.ts +69 -43
- package/src/elements/accented-trigger.ts +52 -43
- package/src/fullscreen-listener.ts +15 -11
- package/src/intersection-observer.ts +27 -16
- package/src/log-and-rethrow.ts +2 -3
- package/src/logger.ts +8 -6
- package/src/register-elements.ts +7 -7
- package/src/resize-listener.ts +15 -11
- package/src/scanner.ts +55 -41
- package/src/scroll-listeners.ts +27 -19
- package/src/state.ts +24 -21
- package/src/task-queue.test.ts +5 -4
- package/src/task-queue.ts +2 -2
- package/src/types.ts +52 -53
- package/src/utils/are-elements-with-issues-equal.ts +7 -5
- package/src/utils/are-issue-sets-equal.test.ts +10 -6
- package/src/utils/are-issue-sets-equal.ts +8 -6
- package/src/utils/containing-blocks.ts +6 -3
- package/src/utils/contains.test.ts +2 -2
- package/src/utils/contains.ts +1 -1
- package/src/utils/deduplicate-nodes.ts +1 -1
- package/src/utils/deep-merge.test.ts +8 -1
- package/src/utils/deep-merge.ts +11 -8
- package/src/utils/dom-helpers.ts +6 -2
- package/src/utils/ensure-non-empty.ts +2 -2
- package/src/utils/get-element-html.ts +4 -2
- package/src/utils/get-element-position.ts +37 -24
- package/src/utils/get-parent.ts +1 -1
- package/src/utils/get-scan-context.test.ts +14 -8
- package/src/utils/get-scan-context.ts +12 -15
- package/src/utils/get-scrollable-ancestors.ts +8 -5
- package/src/utils/is-node-in-scan-context.test.ts +3 -3
- package/src/utils/is-node-in-scan-context.ts +6 -6
- package/src/utils/is-non-empty.ts +3 -0
- package/src/utils/normalize-context.test.ts +9 -9
- package/src/utils/normalize-context.ts +17 -10
- package/src/utils/recalculate-positions.ts +5 -5
- package/src/utils/recalculate-scrollable-ancestors.ts +4 -4
- package/src/utils/shadow-dom-aware-mutation-observer.ts +21 -24
- package/src/utils/supports-anchor-positioning.ts +3 -3
- package/src/utils/transform-violations.test.ts +22 -20
- package/src/utils/transform-violations.ts +14 -10
- package/src/utils/update-elements-with-issues.test.ts +49 -49
- package/src/utils/update-elements-with-issues.ts +96 -71
- package/src/validate-options.ts +91 -38
package/dist/validate-options.js
CHANGED
|
@@ -1,39 +1,37 @@
|
|
|
1
1
|
import { allowedAxeOptions } from './types.js';
|
|
2
2
|
import { isNode, isNodeList } from './utils/dom-helpers.js';
|
|
3
3
|
function isSelector(contextFragment) {
|
|
4
|
-
return typeof contextFragment === 'string'
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
return (typeof contextFragment === 'string' ||
|
|
5
|
+
isNode(contextFragment) ||
|
|
6
|
+
'fromShadowDom' in contextFragment);
|
|
7
7
|
}
|
|
8
8
|
function validateSelector(selector) {
|
|
9
9
|
if (typeof selector === 'string') {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
if (isNode(selector)) {
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
if (!Array.isArray(selector.fromShadowDom)
|
|
17
|
-
|
|
18
|
-
!selector.fromShadowDom.every(item => typeof item === 'string')) {
|
|
15
|
+
if ('fromShadowDom' in selector) {
|
|
16
|
+
if (!Array.isArray(selector.fromShadowDom) ||
|
|
17
|
+
selector.fromShadowDom.length < 2 ||
|
|
18
|
+
!selector.fromShadowDom.every((item) => typeof item === 'string')) {
|
|
19
19
|
throw new TypeError(`Accented: invalid argument. \`fromShadowDom\` must be an array of strings with at least 2 elements. It’s currently set to ${selector.fromShadowDom}.`);
|
|
20
20
|
}
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
throw new TypeError(`Accented: invalid argument. The selector must be one of: string, Node, or an object with a \`fromShadowDom\` property. It’s currently set to ${neverSelector}.`);
|
|
26
|
-
}
|
|
23
|
+
const neverSelector = selector;
|
|
24
|
+
throw new TypeError(`Accented: invalid argument. The selector must be one of: string, Node, or an object with a \`fromShadowDom\` property. It’s currently set to ${neverSelector}.`);
|
|
27
25
|
}
|
|
28
26
|
function isSelectorList(contextFragment) {
|
|
29
|
-
return (typeof contextFragment === 'object' && isNodeList(contextFragment))
|
|
30
|
-
|
|
27
|
+
return ((typeof contextFragment === 'object' && isNodeList(contextFragment)) ||
|
|
28
|
+
(Array.isArray(contextFragment) && contextFragment.every((item) => isSelector(item))));
|
|
31
29
|
}
|
|
32
30
|
function validateSelectorList(selectorList) {
|
|
33
31
|
if (isNodeList(selectorList)) {
|
|
34
32
|
return;
|
|
35
33
|
}
|
|
36
|
-
|
|
34
|
+
if (Array.isArray(selectorList)) {
|
|
37
35
|
for (const selector of selectorList) {
|
|
38
36
|
validateSelector(selector);
|
|
39
37
|
}
|
|
@@ -59,14 +57,15 @@ function validateContextProp(context) {
|
|
|
59
57
|
}
|
|
60
58
|
}
|
|
61
59
|
function isContextObject(contextFragment) {
|
|
62
|
-
return typeof contextFragment === 'object' &&
|
|
63
|
-
|
|
60
|
+
return (typeof contextFragment === 'object' &&
|
|
61
|
+
contextFragment !== null &&
|
|
62
|
+
('include' in contextFragment || 'exclude' in contextFragment));
|
|
64
63
|
}
|
|
65
64
|
function validateContextObject(contextObject) {
|
|
66
|
-
if ('include' in contextObject) {
|
|
65
|
+
if ('include' in contextObject && contextObject.include !== undefined) {
|
|
67
66
|
validateContextProp(contextObject.include);
|
|
68
67
|
}
|
|
69
|
-
if ('exclude' in contextObject) {
|
|
68
|
+
if ('exclude' in contextObject && contextObject.exclude !== undefined) {
|
|
70
69
|
validateContextProp(contextObject.exclude);
|
|
71
70
|
}
|
|
72
71
|
}
|
|
@@ -86,7 +85,7 @@ function validateContext(context) {
|
|
|
86
85
|
// but with Unicode it gets complicated quickly, so I'm sticking to only allowing
|
|
87
86
|
// lowercase alphanumeric names that possibly contain dashes that start with a letter.
|
|
88
87
|
const nameRegex = /^[a-z]([a-z0-9]|-)+$/;
|
|
89
|
-
export
|
|
88
|
+
export function validateOptions(options) {
|
|
90
89
|
if (typeof options !== 'object' || options === null) {
|
|
91
90
|
throw new TypeError(`Accented: invalid argument. The options parameter must be an object if provided. It’s currently set to ${options}.`);
|
|
92
91
|
}
|
|
@@ -94,7 +93,8 @@ export default function validateOptions(options) {
|
|
|
94
93
|
if (typeof options.throttle !== 'object' || options.throttle === null) {
|
|
95
94
|
throw new TypeError(`Accented: invalid argument. \`throttle\` option must be an object if provided. It’s currently set to ${options.throttle}.`);
|
|
96
95
|
}
|
|
97
|
-
if (options.throttle.wait !== undefined &&
|
|
96
|
+
if (options.throttle.wait !== undefined &&
|
|
97
|
+
(typeof options.throttle.wait !== 'number' || options.throttle.wait < 0)) {
|
|
98
98
|
throw new TypeError(`Accented: invalid argument. \`throttle.wait\` option must be a non-negative number if provided. It’s currently set to ${options.throttle.wait}.`);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -109,14 +109,15 @@ export default function validateOptions(options) {
|
|
|
109
109
|
if (options.callback !== undefined && typeof options.callback !== 'function') {
|
|
110
110
|
throw new TypeError(`Accented: invalid argument. \`callback\` option must be a function if provided. It’s currently set to ${options.callback}.`);
|
|
111
111
|
}
|
|
112
|
-
if (options.name !== undefined &&
|
|
112
|
+
if (options.name !== undefined &&
|
|
113
|
+
(typeof options.name !== 'string' || !options.name.match(nameRegex))) {
|
|
113
114
|
throw new TypeError(`Accented: invalid argument. \`name\` option must be a string that starts with a lowercase letter and only contains lowercase alphanumeric characters and dashes. It’s currently set to ${options.name}.`);
|
|
114
115
|
}
|
|
115
116
|
if (options.axeOptions !== undefined) {
|
|
116
117
|
if (typeof options.axeOptions !== 'object' || options.axeOptions === null) {
|
|
117
118
|
throw new TypeError(`Accented: invalid argument. \`axeOptions\` option must be an object if provided. It’s currently set to ${options.axeOptions}.`);
|
|
118
119
|
}
|
|
119
|
-
const unsupportedKeys = Object.keys(options.axeOptions).filter(key => !allowedAxeOptions.includes(key));
|
|
120
|
+
const unsupportedKeys = Object.keys(options.axeOptions).filter((key) => !allowedAxeOptions.includes(key));
|
|
120
121
|
if (unsupportedKeys.length > 0) {
|
|
121
122
|
throw new TypeError(`Accented: invalid argument. \`axeOptions\` contains the following unsupported keys: ${unsupportedKeys.join(', ')}. Valid options are: ${allowedAxeOptions.join(', ')}.`);
|
|
122
123
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-options.js","sourceRoot":"","sources":["../src/validate-options.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate-options.js","sourceRoot":"","sources":["../src/validate-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAS/C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE5D,SAAS,UAAU,CAAC,eAAwB;IAC1C,OAAO,CACL,OAAO,eAAe,KAAK,QAAQ;QACnC,MAAM,CAAC,eAAe,CAAC;QACvB,eAAe,IAAI,eAAe,CACnC,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAkB;IAC1C,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO;IACT,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrB,OAAO;IACT,CAAC;IACD,IAAI,eAAe,IAAI,QAAQ,EAAE,CAAC;QAChC,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;YACtC,QAAQ,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;YACjC,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,EACjE,CAAC;YACD,MAAM,IAAI,SAAS,CACjB,6HAA6H,QAAQ,CAAC,aAAa,GAAG,CACvJ,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IACD,MAAM,aAAa,GAAU,QAAQ,CAAC;IACtC,MAAM,IAAI,SAAS,CACjB,gJAAgJ,aAAa,GAAG,CACjK,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,eAAwB;IAC9C,OAAO,CACL,CAAC,OAAO,eAAe,KAAK,QAAQ,IAAI,UAAU,CAAC,eAAe,CAAC,CAAC;QACpE,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CACtF,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,YAA0B;IACtD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;YACpC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,iBAAiB,GAAU,YAAY,CAAC;QAC9C,MAAM,IAAI,SAAS,CACjB,8GAA8G,iBAAiB,GAAG,CACnI,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,eAAwB;IAC7C,OAAO,UAAU,CAAC,eAAe,CAAC,IAAI,cAAc,CAAC,eAAe,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAgC;IAC3D,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;SAAM,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,MAAM,YAAY,GAAU,OAAO,CAAC;QACpC,MAAM,IAAI,SAAS,CACjB,wHAAwH,YAAY,GAAG,CACxI,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,eAAwB;IAC/C,OAAO,CACL,OAAO,eAAe,KAAK,QAAQ;QACnC,eAAe,KAAK,IAAI;QACxB,CAAC,SAAS,IAAI,eAAe,IAAI,SAAS,IAAI,eAAe,CAAC,CAC/D,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,aAA4B;IACzD,IAAI,SAAS,IAAI,aAAa,IAAI,aAAa,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACtE,mBAAmB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,SAAS,IAAI,aAAa,IAAI,aAAa,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACtE,mBAAmB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,OAAgB;IACvC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;SAAM,IAAI,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,MAAM,YAAY,GAAU,OAAO,CAAC;QACpC,MAAM,IAAI,SAAS,CACjB,6DAA6D,YAAY,GAAG,CAC7E,CAAC;IACJ,CAAC;AACH,CAAC;AAED,4DAA4D;AAC5D,iFAAiF;AACjF,sFAAsF;AACtF,MAAM,SAAS,GAAG,sBAAsB,CAAC;AAEzC,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,MAAM,IAAI,SAAS,CACjB,0GAA0G,OAAO,GAAG,CACrH,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtE,MAAM,IAAI,SAAS,CACjB,wGAAwG,OAAO,CAAC,QAAQ,GAAG,CAC5H,CAAC;QACJ,CAAC;QACD,IACE,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS;YACnC,CAAC,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC,EACxE,CAAC;YACD,MAAM,IAAI,SAAS,CACjB,yHAAyH,OAAO,CAAC,QAAQ,CAAC,IAAI,GAAG,CAClJ,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAClE,MAAM,IAAI,SAAS,CACjB,sGAAsG,OAAO,CAAC,MAAM,GAAG,CACxH,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACxF,OAAO,CAAC,IAAI,CACV,4GAA4G,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,CACtI,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC7E,MAAM,IAAI,SAAS,CACjB,yGAAyG,OAAO,CAAC,QAAQ,GAAG,CAC7H,CAAC;IACJ,CAAC;IACD,IACE,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,CAAC,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EACpE,CAAC;QACD,MAAM,IAAI,SAAS,CACjB,0LAA0L,OAAO,CAAC,IAAI,GAAG,CAC1M,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACrC,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC1E,MAAM,IAAI,SAAS,CACjB,0GAA0G,OAAO,CAAC,UAAU,GAAG,CAChI,CAAC;QACJ,CAAC;QACD,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAC5D,CAAC,GAAG,EAAE,EAAE,CAAC,CAAE,iBAA8C,CAAC,QAAQ,CAAC,GAAG,CAAC,CACxE,CAAC;QACF,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,SAAS,CACjB,uFAAuF,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACzK,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "accented",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-20250618181418",
|
|
4
4
|
"description": "Continuous accessibility testing and issue highlighting for web development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/accented.js",
|
|
@@ -34,11 +34,13 @@
|
|
|
34
34
|
"jsdom": "^26.0.0"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
|
-
"build": "tsc",
|
|
37
|
+
"build": "pnpm copyCommon && tsc",
|
|
38
|
+
"copyCommon": "node --import tsx ./scripts/copy-common.ts",
|
|
39
|
+
"watchCommon": "node --import tsx ./scripts/watch-common.ts",
|
|
38
40
|
"checkBuiltFiles": "node --import tsx ./scripts/check-built-files.ts",
|
|
39
41
|
"checkImportsInBuiltFiles": "node ./dist/accented.js",
|
|
40
42
|
"typecheckTests": "tsc -p ./tsconfig.test.json",
|
|
41
|
-
"watch": "tsc --watch",
|
|
43
|
+
"watch": "pnpm copyCommon && (pnpm watchCommon & tsc --watch)",
|
|
42
44
|
"test": "node --test --import tsx \"./**/*.test.ts\""
|
|
43
45
|
}
|
|
44
46
|
}
|
package/src/accented.test.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
|
-
import {suite, test} from 'node:test';
|
|
2
|
+
import { suite, test } from 'node:test';
|
|
3
3
|
import type { Mock } from 'node:test';
|
|
4
4
|
|
|
5
|
-
import accented from './accented
|
|
5
|
+
import { accented } from './accented';
|
|
6
6
|
|
|
7
7
|
suite('Accented', () => {
|
|
8
8
|
test('runs without errors in NodeJS and issues a warning and a trace (it’s meant to be a no-op on the server side)', (t) => {
|
package/src/accented.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import setupResizeListener from './resize-listener.js';
|
|
8
|
-
import
|
|
9
|
-
import
|
|
1
|
+
import { createDomUpdater } from './dom-updater.js';
|
|
2
|
+
import { setupResizeListener as setupFullscreenListener } from './fullscreen-listener.js';
|
|
3
|
+
import { setupIntersectionObserver } from './intersection-observer.js';
|
|
4
|
+
import { logAndRethrow } from './log-and-rethrow.js';
|
|
5
|
+
import { createLogger } from './logger.js';
|
|
6
|
+
import { registerElements } from './register-elements.js';
|
|
7
|
+
import { setupResizeListener } from './resize-listener.js';
|
|
8
|
+
import { createScanner } from './scanner.js';
|
|
9
|
+
import { setupScrollListeners } from './scroll-listeners.js';
|
|
10
10
|
import { enabled, extendedElementsWithIssues } from './state.js';
|
|
11
|
-
import
|
|
12
|
-
import type { AccentedOptions, DisableAccented } from './types';
|
|
13
|
-
import validateOptions from './validate-options.js';
|
|
14
|
-
import supportsAnchorPositioning from './utils/supports-anchor-positioning.js';
|
|
15
|
-
import logAndRethrow from './log-and-rethrow.js';
|
|
11
|
+
import type { AccentedOptions, DisableAccented } from './types.ts';
|
|
16
12
|
import { initializeContainingBlockSupportSet } from './utils/containing-blocks.js';
|
|
13
|
+
import { deepMerge } from './utils/deep-merge.js';
|
|
14
|
+
import { supportsAnchorPositioning } from './utils/supports-anchor-positioning.js';
|
|
15
|
+
import { validateOptions } from './validate-options.js';
|
|
17
16
|
|
|
18
17
|
export type { AccentedOptions, DisableAccented };
|
|
19
18
|
|
|
@@ -42,24 +41,25 @@ export type { AccentedOptions, DisableAccented };
|
|
|
42
41
|
* }
|
|
43
42
|
* });
|
|
44
43
|
*/
|
|
45
|
-
export
|
|
46
|
-
|
|
44
|
+
export function accented(options: AccentedOptions = {}): DisableAccented {
|
|
47
45
|
validateOptions(options);
|
|
48
46
|
|
|
49
47
|
try {
|
|
50
48
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
51
|
-
console.warn(
|
|
49
|
+
console.warn(
|
|
50
|
+
'Accented: this script can only run in the browser, and it’s likely running on the server now. Exiting.',
|
|
51
|
+
);
|
|
52
52
|
console.trace();
|
|
53
53
|
return () => {};
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const defaultOutput: Required<AccentedOptions['output']> = {
|
|
57
|
-
console: true
|
|
57
|
+
console: true,
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
const defaultThrottle: Required<AccentedOptions['throttle']> = {
|
|
61
61
|
wait: 1000,
|
|
62
|
-
leading: true
|
|
62
|
+
leading: true,
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
// IMPORTANT: when changing any of the properties or values, also do the following:
|
|
@@ -73,16 +73,19 @@ export default function accented(options: AccentedOptions = {}): DisableAccented
|
|
|
73
73
|
name: 'accented',
|
|
74
74
|
output: defaultOutput,
|
|
75
75
|
throttle: defaultThrottle,
|
|
76
|
-
callback: () => {}
|
|
76
|
+
callback: () => {},
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
-
const {context, axeOptions, name, output, throttle, callback} = deepMerge(
|
|
79
|
+
const { context, axeOptions, name, output, throttle, callback } = deepMerge(
|
|
80
|
+
defaultOptions,
|
|
81
|
+
options,
|
|
82
|
+
);
|
|
80
83
|
|
|
81
84
|
if (enabled.value) {
|
|
82
85
|
// Add link to the recipes section of the docs (#56).
|
|
83
86
|
console.warn(
|
|
84
87
|
'You are trying to run the Accented library more than once. ' +
|
|
85
|
-
|
|
88
|
+
'This will likely lead to errors.',
|
|
86
89
|
);
|
|
87
90
|
console.trace();
|
|
88
91
|
}
|
|
@@ -92,13 +95,18 @@ export default function accented(options: AccentedOptions = {}): DisableAccented
|
|
|
92
95
|
initializeContainingBlockSupportSet();
|
|
93
96
|
registerElements(name);
|
|
94
97
|
|
|
95
|
-
const {disconnect: cleanupIntersectionObserver, intersectionObserver } =
|
|
98
|
+
const { disconnect: cleanupIntersectionObserver, intersectionObserver } =
|
|
99
|
+
setupIntersectionObserver();
|
|
96
100
|
const cleanupScanner = createScanner(name, context, axeOptions, throttle, callback);
|
|
97
101
|
const cleanupDomUpdater = createDomUpdater(name, intersectionObserver);
|
|
98
102
|
const cleanupLogger = output.console ? createLogger() : () => {};
|
|
99
|
-
const cleanupScrollListeners =
|
|
100
|
-
const cleanupResizeListener = supportsAnchorPositioning(window)
|
|
101
|
-
|
|
103
|
+
const cleanupScrollListeners = setupScrollListeners();
|
|
104
|
+
const cleanupResizeListener = supportsAnchorPositioning(window)
|
|
105
|
+
? () => {}
|
|
106
|
+
: setupResizeListener();
|
|
107
|
+
const cleanupFullscreenListener = supportsAnchorPositioning(window)
|
|
108
|
+
? () => {}
|
|
109
|
+
: setupFullscreenListener();
|
|
102
110
|
|
|
103
111
|
return () => {
|
|
104
112
|
try {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const primaryColor = 'oklch(0.5 0.3 0)';
|
package/src/dom-updater.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { effect } from '@preact/signals-core';
|
|
2
|
+
import { primaryColor } from './common/tokens.js';
|
|
2
3
|
import { extendedElementsWithIssues, rootNodes } from './state.js';
|
|
3
|
-
import type { ExtendedElementWithIssues } from './types';
|
|
4
|
-
import areElementsWithIssuesEqual from './utils/are-elements-with-issues-equal.js';
|
|
5
|
-
import supportsAnchorPositioning from './utils/supports-anchor-positioning.js';
|
|
4
|
+
import type { ExtendedElementWithIssues } from './types.ts';
|
|
5
|
+
import { areElementsWithIssuesEqual } from './utils/are-elements-with-issues-equal.js';
|
|
6
6
|
import { isDocument, isDocumentFragment, isShadowRoot } from './utils/dom-helpers.js';
|
|
7
|
-
import getParent from './utils/get-parent.js';
|
|
7
|
+
import { getParent } from './utils/get-parent.js';
|
|
8
|
+
import { supportsAnchorPositioning } from './utils/supports-anchor-positioning.js';
|
|
8
9
|
|
|
9
10
|
const shouldInsertTriggerInsideElement = (element: Element): boolean => {
|
|
10
11
|
/**
|
|
@@ -30,17 +31,17 @@ const shouldInsertTriggerInsideElement = (element: Element): boolean => {
|
|
|
30
31
|
return noParent || isTableCell || isSummary;
|
|
31
32
|
};
|
|
32
33
|
|
|
33
|
-
export
|
|
34
|
+
export function createDomUpdater(name: string, intersectionObserver?: IntersectionObserver) {
|
|
34
35
|
const attrName = `data-${name}`;
|
|
35
36
|
|
|
36
|
-
function getAnchorNames
|
|
37
|
+
function getAnchorNames(anchorNameValue: string) {
|
|
37
38
|
return anchorNameValue
|
|
38
39
|
.split(',')
|
|
39
|
-
.map(anchorName => anchorName.trim())
|
|
40
|
-
.filter(anchorName => anchorName.startsWith('--'));
|
|
40
|
+
.map((anchorName) => anchorName.trim())
|
|
41
|
+
.filter((anchorName) => anchorName.startsWith('--'));
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
function setAnchorName
|
|
44
|
+
function setAnchorName(elementWithIssues: ExtendedElementWithIssues) {
|
|
44
45
|
const { element, id, anchorNameValue } = elementWithIssues;
|
|
45
46
|
const anchorNames = getAnchorNames(anchorNameValue);
|
|
46
47
|
if (anchorNames.length > 0) {
|
|
@@ -50,7 +51,7 @@ export default function createDomUpdater(name: string, intersectionObserver?: In
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
function removeAnchorName
|
|
54
|
+
function removeAnchorName(elementWithIssues: ExtendedElementWithIssues) {
|
|
54
55
|
const { element, anchorNameValue } = elementWithIssues;
|
|
55
56
|
const anchorNames = getAnchorNames(anchorNameValue);
|
|
56
57
|
if (anchorNames.length > 0) {
|
|
@@ -60,7 +61,7 @@ export default function createDomUpdater(name: string, intersectionObserver?: In
|
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
function setIssues
|
|
64
|
+
function setIssues(extendedElementsWithIssues: Array<ExtendedElementWithIssues>) {
|
|
64
65
|
for (const elementWithIssues of extendedElementsWithIssues) {
|
|
65
66
|
if (elementWithIssues.skipRender) {
|
|
66
67
|
continue;
|
|
@@ -81,7 +82,7 @@ export default function createDomUpdater(name: string, intersectionObserver?: In
|
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
function removeIssues
|
|
85
|
+
function removeIssues(extendedElementsWithIssues: Array<ExtendedElementWithIssues>) {
|
|
85
86
|
for (const elementWithIssues of extendedElementsWithIssues) {
|
|
86
87
|
if (elementWithIssues.skipRender) {
|
|
87
88
|
continue;
|
|
@@ -103,7 +104,7 @@ export default function createDomUpdater(name: string, intersectionObserver?: In
|
|
|
103
104
|
:root {
|
|
104
105
|
/* Ensure that the primary / secondary color combination meets WCAG 1.4.3 Contrast (Minimum) */
|
|
105
106
|
/* OKLCH stuff: https://oklch.com/ */
|
|
106
|
-
--${name}-primary-color:
|
|
107
|
+
--${name}-primary-color: ${primaryColor};
|
|
107
108
|
--${name}-secondary-color: oklch(0.98 0 0);
|
|
108
109
|
--${name}-outline-width: 2px;
|
|
109
110
|
--${name}-outline-style: solid;
|
|
@@ -124,8 +125,10 @@ export default function createDomUpdater(name: string, intersectionObserver?: In
|
|
|
124
125
|
|
|
125
126
|
const disposeOfStyleSheetsEffect = effect(() => {
|
|
126
127
|
const newRootNodes = rootNodes.value;
|
|
127
|
-
const addedRootNodes = [...newRootNodes].filter(rootNode => !previousRootNodes.has(rootNode));
|
|
128
|
-
const removedRootNodes = [...previousRootNodes].filter(
|
|
128
|
+
const addedRootNodes = [...newRootNodes].filter((rootNode) => !previousRootNodes.has(rootNode));
|
|
129
|
+
const removedRootNodes = [...previousRootNodes].filter(
|
|
130
|
+
(rootNode) => !newRootNodes.has(rootNode),
|
|
131
|
+
);
|
|
129
132
|
for (const rootNode of addedRootNodes) {
|
|
130
133
|
if (isDocument(rootNode) || (isDocumentFragment(rootNode) && isShadowRoot(rootNode))) {
|
|
131
134
|
rootNode.adoptedStyleSheets.push(stylesheet);
|
|
@@ -140,11 +143,15 @@ export default function createDomUpdater(name: string, intersectionObserver?: In
|
|
|
140
143
|
});
|
|
141
144
|
|
|
142
145
|
const disposeOfElementsEffect = effect(() => {
|
|
143
|
-
const added = extendedElementsWithIssues.value.filter(elementWithIssues => {
|
|
144
|
-
return !previousExtendedElementsWithIssues.some(previousElementWithIssues =>
|
|
146
|
+
const added = extendedElementsWithIssues.value.filter((elementWithIssues) => {
|
|
147
|
+
return !previousExtendedElementsWithIssues.some((previousElementWithIssues) =>
|
|
148
|
+
areElementsWithIssuesEqual(previousElementWithIssues, elementWithIssues),
|
|
149
|
+
);
|
|
145
150
|
});
|
|
146
|
-
const removed = previousExtendedElementsWithIssues.filter(previousElementWithIssues => {
|
|
147
|
-
return !extendedElementsWithIssues.value.some(elementWithIssues =>
|
|
151
|
+
const removed = previousExtendedElementsWithIssues.filter((previousElementWithIssues) => {
|
|
152
|
+
return !extendedElementsWithIssues.value.some((elementWithIssues) =>
|
|
153
|
+
areElementsWithIssuesEqual(elementWithIssues, previousElementWithIssues),
|
|
154
|
+
);
|
|
148
155
|
});
|
|
149
156
|
removeIssues(removed);
|
|
150
157
|
setIssues(added);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { Issue } from '../types';
|
|
2
1
|
import type { Signal } from '@preact/signals-core';
|
|
3
|
-
import getElementHtml from '../utils/get-element-html.js';
|
|
4
2
|
import { accentedUrl } from '../constants.js';
|
|
5
|
-
import logAndRethrow from '../log-and-rethrow.js';
|
|
3
|
+
import { logAndRethrow } from '../log-and-rethrow.js';
|
|
4
|
+
import type { Issue } from '../types.ts';
|
|
5
|
+
import { getElementHtml } from '../utils/get-element-html.js';
|
|
6
|
+
import { isNonEmpty } from '../utils/is-non-empty.js';
|
|
6
7
|
|
|
7
8
|
export interface AccentedDialog extends HTMLElement {
|
|
8
9
|
issues: Signal<Array<Issue>> | undefined;
|
|
@@ -13,7 +14,7 @@ export interface AccentedDialog extends HTMLElement {
|
|
|
13
14
|
|
|
14
15
|
// We want Accented to not throw an error in Node, and use static imports,
|
|
15
16
|
// so we can't export `class extends HTMLElement` because HTMLElement is not available in Node.
|
|
16
|
-
export
|
|
17
|
+
export const getAccentedDialog = () => {
|
|
17
18
|
const dialogTemplate = document.createElement('template');
|
|
18
19
|
dialogTemplate.innerHTML = `
|
|
19
20
|
<dialog dir="ltr" lang="en" aria-labelledby="title">
|
|
@@ -247,11 +248,11 @@ export default () => {
|
|
|
247
248
|
|
|
248
249
|
element: Element | undefined;
|
|
249
250
|
|
|
250
|
-
open
|
|
251
|
+
open = false;
|
|
251
252
|
|
|
252
253
|
constructor() {
|
|
254
|
+
super();
|
|
253
255
|
try {
|
|
254
|
-
super();
|
|
255
256
|
this.attachShadow({ mode: 'open' });
|
|
256
257
|
const content = dialogTemplate.content.cloneNode(true);
|
|
257
258
|
if (this.shadowRoot) {
|
|
@@ -270,31 +271,43 @@ export default () => {
|
|
|
270
271
|
const dialog = shadowRoot.querySelector('dialog');
|
|
271
272
|
const closeButton = shadowRoot.querySelector('#close');
|
|
272
273
|
this.#abortController = new AbortController();
|
|
273
|
-
closeButton?.addEventListener(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
dialog?.addEventListener('click', (event) => {
|
|
282
|
-
try {
|
|
283
|
-
this.#onDialogClick(event);
|
|
284
|
-
} catch (error) {
|
|
285
|
-
logAndRethrow(error);
|
|
286
|
-
}
|
|
287
|
-
}, { signal: this.#abortController.signal });
|
|
288
|
-
|
|
289
|
-
dialog?.addEventListener('keydown', (event) => {
|
|
290
|
-
try {
|
|
291
|
-
if (event.key === 'Escape') {
|
|
292
|
-
event.stopPropagation();
|
|
274
|
+
closeButton?.addEventListener(
|
|
275
|
+
'click',
|
|
276
|
+
() => {
|
|
277
|
+
try {
|
|
278
|
+
dialog?.close();
|
|
279
|
+
} catch (error) {
|
|
280
|
+
logAndRethrow(error);
|
|
293
281
|
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
282
|
+
},
|
|
283
|
+
{ signal: this.#abortController.signal },
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
dialog?.addEventListener(
|
|
287
|
+
'click',
|
|
288
|
+
(event) => {
|
|
289
|
+
try {
|
|
290
|
+
this.#onDialogClick(event);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
logAndRethrow(error);
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
{ signal: this.#abortController.signal },
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
dialog?.addEventListener(
|
|
299
|
+
'keydown',
|
|
300
|
+
(event) => {
|
|
301
|
+
try {
|
|
302
|
+
if (event.key === 'Escape') {
|
|
303
|
+
event.stopPropagation();
|
|
304
|
+
}
|
|
305
|
+
} catch (error) {
|
|
306
|
+
logAndRethrow(error);
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
{ signal: this.#abortController.signal },
|
|
310
|
+
);
|
|
298
311
|
|
|
299
312
|
if (this.issues) {
|
|
300
313
|
const issues = this.issues.value;
|
|
@@ -307,18 +320,23 @@ export default () => {
|
|
|
307
320
|
const impact = issueContent.querySelector('.impact');
|
|
308
321
|
const description = issueContent.querySelector('.description');
|
|
309
322
|
if (title && impact && description) {
|
|
310
|
-
title.textContent = issue.title
|
|
323
|
+
title.textContent = `${issue.title} (${issue.id})`;
|
|
311
324
|
title.href = issue.url;
|
|
312
325
|
|
|
313
|
-
impact.textContent =
|
|
326
|
+
impact.textContent = `User impact: ${issue.impact}`;
|
|
314
327
|
impact.setAttribute('data-impact', String(issue.impact));
|
|
315
328
|
|
|
316
329
|
const descriptionItems = issue.description.split(/\n\s*/);
|
|
317
330
|
const descriptionContent = descriptionTemplate.content.cloneNode(true) as Element;
|
|
318
331
|
const descriptionTitle = descriptionContent.querySelector('span');
|
|
319
332
|
const descriptionList = descriptionContent.querySelector('ul');
|
|
320
|
-
if (
|
|
321
|
-
descriptionTitle
|
|
333
|
+
if (
|
|
334
|
+
descriptionTitle &&
|
|
335
|
+
descriptionList &&
|
|
336
|
+
isNonEmpty(descriptionItems) &&
|
|
337
|
+
descriptionItems.length > 1
|
|
338
|
+
) {
|
|
339
|
+
descriptionTitle.textContent = descriptionItems[0];
|
|
322
340
|
for (const descriptionItem of descriptionItems.slice(1)) {
|
|
323
341
|
const li = document.createElement('li');
|
|
324
342
|
li.textContent = descriptionItem;
|
|
@@ -339,14 +357,18 @@ export default () => {
|
|
|
339
357
|
}
|
|
340
358
|
}
|
|
341
359
|
|
|
342
|
-
dialog?.addEventListener(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
360
|
+
dialog?.addEventListener(
|
|
361
|
+
'close',
|
|
362
|
+
() => {
|
|
363
|
+
try {
|
|
364
|
+
this.open = false;
|
|
365
|
+
this.dispatchEvent(new Event('close'));
|
|
366
|
+
} catch (error) {
|
|
367
|
+
logAndRethrow(error);
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
{ signal: this.#abortController.signal },
|
|
371
|
+
);
|
|
350
372
|
}
|
|
351
373
|
} catch (error) {
|
|
352
374
|
logAndRethrow(error);
|
|
@@ -375,7 +397,11 @@ export default () => {
|
|
|
375
397
|
|
|
376
398
|
#onDialogClick(event: MouseEvent) {
|
|
377
399
|
const dialog = event.currentTarget as HTMLDialogElement;
|
|
378
|
-
if (
|
|
400
|
+
if (
|
|
401
|
+
!dialog ||
|
|
402
|
+
typeof dialog.getBoundingClientRect !== 'function' ||
|
|
403
|
+
typeof dialog.close !== 'function'
|
|
404
|
+
) {
|
|
379
405
|
return;
|
|
380
406
|
}
|
|
381
407
|
const rect = dialog.getBoundingClientRect();
|