accented 0.0.1-dev.4 → 0.0.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.
Files changed (142) hide show
  1. package/README.md +214 -0
  2. package/dist/accented.d.ts +28 -7
  3. package/dist/accented.d.ts.map +1 -1
  4. package/dist/accented.js +100 -42
  5. package/dist/accented.js.map +1 -1
  6. package/dist/constants.d.ts +3 -0
  7. package/dist/constants.d.ts.map +1 -0
  8. package/dist/constants.js +3 -0
  9. package/dist/constants.js.map +1 -0
  10. package/dist/dom-updater.d.ts +1 -6
  11. package/dist/dom-updater.d.ts.map +1 -1
  12. package/dist/dom-updater.js +94 -20
  13. package/dist/dom-updater.js.map +1 -1
  14. package/dist/elements/accented-dialog.d.ts +356 -0
  15. package/dist/elements/accented-dialog.d.ts.map +1 -0
  16. package/dist/elements/accented-dialog.js +361 -0
  17. package/dist/elements/accented-dialog.js.map +1 -0
  18. package/dist/elements/accented-trigger.d.ts +359 -0
  19. package/dist/elements/accented-trigger.d.ts.map +1 -0
  20. package/dist/elements/accented-trigger.js +159 -0
  21. package/dist/elements/accented-trigger.js.map +1 -0
  22. package/dist/intersection-observer.d.ts +5 -0
  23. package/dist/intersection-observer.d.ts.map +1 -0
  24. package/dist/intersection-observer.js +28 -0
  25. package/dist/intersection-observer.js.map +1 -0
  26. package/dist/log-and-rethrow.d.ts +2 -0
  27. package/dist/log-and-rethrow.d.ts.map +1 -0
  28. package/dist/log-and-rethrow.js +7 -0
  29. package/dist/log-and-rethrow.js.map +1 -0
  30. package/dist/logger.d.ts +2 -0
  31. package/dist/logger.d.ts.map +1 -0
  32. package/dist/logger.js +25 -0
  33. package/dist/logger.js.map +1 -0
  34. package/dist/register-elements.d.ts +2 -0
  35. package/dist/register-elements.d.ts.map +1 -0
  36. package/dist/register-elements.js +21 -0
  37. package/dist/register-elements.js.map +1 -0
  38. package/dist/resize-listener.d.ts +2 -0
  39. package/dist/resize-listener.d.ts.map +1 -0
  40. package/dist/resize-listener.js +18 -0
  41. package/dist/resize-listener.js.map +1 -0
  42. package/dist/scanner.d.ts +3 -0
  43. package/dist/scanner.d.ts.map +1 -0
  44. package/dist/scanner.js +120 -0
  45. package/dist/scanner.js.map +1 -0
  46. package/dist/scroll-listeners.d.ts +2 -0
  47. package/dist/scroll-listeners.d.ts.map +1 -0
  48. package/dist/scroll-listeners.js +38 -0
  49. package/dist/scroll-listeners.js.map +1 -0
  50. package/dist/state.d.ts +6 -0
  51. package/dist/state.d.ts.map +1 -0
  52. package/dist/state.js +14 -0
  53. package/dist/state.js.map +1 -0
  54. package/dist/task-queue.d.ts +3 -4
  55. package/dist/task-queue.d.ts.map +1 -1
  56. package/dist/task-queue.js +27 -23
  57. package/dist/task-queue.js.map +1 -1
  58. package/dist/types.d.ts +136 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/utils/are-issue-sets-equal.d.ts +3 -0
  63. package/dist/utils/are-issue-sets-equal.d.ts.map +1 -0
  64. package/dist/utils/are-issue-sets-equal.js +6 -0
  65. package/dist/utils/are-issue-sets-equal.js.map +1 -0
  66. package/dist/utils/deep-merge.d.ts +4 -0
  67. package/dist/utils/deep-merge.d.ts.map +1 -0
  68. package/dist/utils/deep-merge.js +18 -0
  69. package/dist/utils/deep-merge.js.map +1 -0
  70. package/dist/utils/get-element-html.d.ts +2 -0
  71. package/dist/utils/get-element-html.d.ts.map +1 -0
  72. package/dist/utils/get-element-html.js +14 -0
  73. package/dist/utils/get-element-html.js.map +1 -0
  74. package/dist/utils/get-element-position.d.ts +3 -0
  75. package/dist/utils/get-element-position.d.ts.map +1 -0
  76. package/dist/utils/get-element-position.js +22 -0
  77. package/dist/utils/get-element-position.js.map +1 -0
  78. package/dist/utils/get-scrollable-ancestors.d.ts +2 -0
  79. package/dist/utils/get-scrollable-ancestors.d.ts.map +1 -0
  80. package/dist/utils/get-scrollable-ancestors.js +15 -0
  81. package/dist/utils/get-scrollable-ancestors.js.map +1 -0
  82. package/dist/utils/recalculate-positions.d.ts +2 -0
  83. package/dist/utils/recalculate-positions.d.ts.map +1 -0
  84. package/dist/utils/recalculate-positions.js +27 -0
  85. package/dist/utils/recalculate-positions.js.map +1 -0
  86. package/dist/utils/recalculate-scrollable-ancestors.d.ts +2 -0
  87. package/dist/utils/recalculate-scrollable-ancestors.d.ts.map +1 -0
  88. package/dist/utils/recalculate-scrollable-ancestors.js +13 -0
  89. package/dist/utils/recalculate-scrollable-ancestors.js.map +1 -0
  90. package/dist/utils/supports-anchor-positioning.d.ts +6 -0
  91. package/dist/utils/supports-anchor-positioning.d.ts.map +1 -0
  92. package/dist/utils/supports-anchor-positioning.js +4 -0
  93. package/dist/utils/supports-anchor-positioning.js.map +1 -0
  94. package/dist/utils/transform-violations.d.ts +4 -0
  95. package/dist/utils/transform-violations.d.ts.map +1 -0
  96. package/dist/utils/transform-violations.js +48 -0
  97. package/dist/utils/transform-violations.js.map +1 -0
  98. package/dist/utils/update-elements-with-issues.d.ts +7 -0
  99. package/dist/utils/update-elements-with-issues.d.ts.map +1 -0
  100. package/dist/utils/update-elements-with-issues.js +64 -0
  101. package/dist/utils/update-elements-with-issues.js.map +1 -0
  102. package/dist/validate-options.d.ts +3 -0
  103. package/dist/validate-options.d.ts.map +1 -0
  104. package/dist/validate-options.js +42 -0
  105. package/dist/validate-options.js.map +1 -0
  106. package/package.json +9 -4
  107. package/src/accented.test.ts +24 -0
  108. package/src/accented.ts +119 -0
  109. package/src/constants.ts +2 -0
  110. package/src/dom-updater.ts +112 -0
  111. package/src/elements/accented-dialog.ts +384 -0
  112. package/src/elements/accented-trigger.ts +179 -0
  113. package/src/intersection-observer.ts +28 -0
  114. package/src/log-and-rethrow.ts +9 -0
  115. package/src/logger.ts +26 -0
  116. package/src/register-elements.ts +21 -0
  117. package/src/resize-listener.ts +17 -0
  118. package/src/scanner.ts +139 -0
  119. package/src/scroll-listeners.ts +37 -0
  120. package/src/state.ts +24 -0
  121. package/src/task-queue.test.ts +135 -0
  122. package/src/task-queue.ts +59 -0
  123. package/src/types.ts +155 -0
  124. package/src/utils/are-issue-sets-equal.test.ts +49 -0
  125. package/src/utils/are-issue-sets-equal.ts +10 -0
  126. package/src/utils/deep-merge.test.ts +34 -0
  127. package/src/utils/deep-merge.ts +18 -0
  128. package/src/utils/get-element-html.ts +13 -0
  129. package/src/utils/get-element-position.ts +21 -0
  130. package/src/utils/get-scrollable-ancestors.ts +14 -0
  131. package/src/utils/recalculate-positions.ts +27 -0
  132. package/src/utils/recalculate-scrollable-ancestors.ts +13 -0
  133. package/src/utils/supports-anchor-positioning.ts +7 -0
  134. package/src/utils/transform-violations.test.ts +124 -0
  135. package/src/utils/transform-violations.ts +56 -0
  136. package/src/utils/update-elements-with-issues.test.ts +283 -0
  137. package/src/utils/update-elements-with-issues.ts +75 -0
  138. package/src/validate-options.ts +44 -0
  139. package/dist/utils/issuesToElements.d.ts +0 -3
  140. package/dist/utils/issuesToElements.d.ts.map +0 -1
  141. package/dist/utils/issuesToElements.js +0 -16
  142. package/dist/utils/issuesToElements.js.map +0 -1
@@ -0,0 +1,75 @@
1
+ import type { AxeResults } from 'axe-core';
2
+ import type { Signal } from '@preact/signals-core';
3
+ import { batch, signal } from '@preact/signals-core';
4
+ import type { ExtendedElementWithIssues } from '../types';
5
+ import transformViolations from './transform-violations.js';
6
+ import areIssueSetsEqual from './are-issue-sets-equal.js';
7
+ import type { AccentedTrigger } from '../elements/accented-trigger';
8
+ import type { AccentedDialog } from '../elements/accented-dialog';
9
+ import getElementPosition from './get-element-position.js';
10
+ import getScrollableAncestors from './get-scrollable-ancestors.js';
11
+ import supportsAnchorPositioning from './supports-anchor-positioning.js';
12
+
13
+ let count = 0;
14
+
15
+ export default function updateElementsWithIssues(extendedElementsWithIssues: Signal<Array<ExtendedElementWithIssues>>, violations: typeof AxeResults.violations, win: Window & { CSS: typeof CSS }, name: string) {
16
+ const updatedElementsWithIssues = transformViolations(violations);
17
+
18
+ batch(() => {
19
+ for (const updatedElementWithIssues of updatedElementsWithIssues) {
20
+ const existingElementIndex = extendedElementsWithIssues.value.findIndex(extendedElementWithIssues => extendedElementWithIssues.element === updatedElementWithIssues.element);
21
+ if (existingElementIndex > -1 && extendedElementsWithIssues.value[existingElementIndex] && !areIssueSetsEqual(extendedElementsWithIssues.value[existingElementIndex].issues.value, updatedElementWithIssues.issues)) {
22
+ extendedElementsWithIssues.value[existingElementIndex].issues.value = updatedElementWithIssues.issues;
23
+ }
24
+ }
25
+
26
+ const addedElementsWithIssues = updatedElementsWithIssues.filter(updatedElementWithIssues => {
27
+ return !extendedElementsWithIssues.value.some(extendedElementWithIssues => extendedElementWithIssues.element === updatedElementWithIssues.element);
28
+ });
29
+
30
+ const removedElementsWithIssues = extendedElementsWithIssues.value.filter(extendedElementWithIssues => {
31
+ return !updatedElementsWithIssues.some(updatedElementWithIssues => updatedElementWithIssues.element === extendedElementWithIssues.element);
32
+ });
33
+
34
+ if (addedElementsWithIssues.length > 0 || removedElementsWithIssues.length > 0) {
35
+ extendedElementsWithIssues.value = [...extendedElementsWithIssues.value]
36
+ .filter(extendedElementWithIssues => {
37
+ return !removedElementsWithIssues.some(removedElementWithIssues => removedElementWithIssues.element === extendedElementWithIssues.element);
38
+ })
39
+ .concat(addedElementsWithIssues
40
+ .filter(addedElementWithIssues => addedElementWithIssues.element.isConnected)
41
+ .map(addedElementWithIssues => {
42
+ const id = count++;
43
+ const trigger = win.document.createElement(`${name}-trigger`) as AccentedTrigger;
44
+ const elementZIndex = parseInt(win.getComputedStyle(addedElementWithIssues.element).zIndex, 10);
45
+ if (!isNaN(elementZIndex)) {
46
+ trigger.style.setProperty('z-index', (elementZIndex + 1).toString(), 'important');
47
+ }
48
+ trigger.style.setProperty('position-anchor', `--${name}-anchor-${id}`, 'important');
49
+ trigger.dataset.id = id.toString();
50
+ const accentedDialog = win.document.createElement(`${name}-dialog`) as AccentedDialog;
51
+ trigger.dialog = accentedDialog;
52
+ const position = getElementPosition(addedElementWithIssues.element, win);
53
+ trigger.position = signal(position);
54
+ trigger.visible = signal(true);
55
+ trigger.element = addedElementWithIssues.element;
56
+ const scrollableAncestors = supportsAnchorPositioning(win) ?
57
+ new Set<HTMLElement>() :
58
+ getScrollableAncestors(addedElementWithIssues.element, win);
59
+ const issues = signal(addedElementWithIssues.issues);
60
+ accentedDialog.issues = issues;
61
+ accentedDialog.element = addedElementWithIssues.element;
62
+ return {
63
+ id,
64
+ element: addedElementWithIssues.element,
65
+ visible: trigger.visible,
66
+ position: trigger.position,
67
+ scrollableAncestors: signal(scrollableAncestors),
68
+ trigger,
69
+ issues
70
+ };
71
+ })
72
+ );
73
+ }
74
+ });
75
+ }
@@ -0,0 +1,44 @@
1
+ import type { AccentedOptions } from './types';
2
+ import { allowedAxeOptions } from './types.js';
3
+
4
+ // The space of valid CSS and HTML names is wider than this,
5
+ // but with Unicode it gets complicated quickly, so I'm sticking to only allowing
6
+ // lowercase alphanumeric names that possibly contain dashes that start with a letter.
7
+ const nameRegex = /^[a-z]([a-z0-9]|-)+$/;
8
+
9
+ export default function validateOptions(options: AccentedOptions) {
10
+ if (typeof options !== 'object' || options === null) {
11
+ throw new TypeError(`Accented: invalid argument. The options parameter must be an object if provided. It’s currently set to ${options}.`);
12
+ }
13
+ if (options.throttle !== undefined) {
14
+ if (typeof options.throttle !== 'object' || options.throttle === null) {
15
+ throw new TypeError(`Accented: invalid argument. \`throttle\` option must be an object if provided. It’s currently set to ${options.throttle}.`);
16
+ }
17
+ if (options.throttle.wait !== undefined && (typeof options.throttle.wait !== 'number' || options.throttle.wait < 0)) {
18
+ 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}.`);
19
+ }
20
+ }
21
+ if (options.output !== undefined) {
22
+ if (typeof options.output !== 'object' || options.output === null) {
23
+ throw new TypeError(`Accented: invalid argument. \`output\` option must be an object if provided. It’s currently set to ${options.output}.`);
24
+ }
25
+ if (options.output.console !== undefined && typeof options.output.console !== 'boolean') {
26
+ console.warn(`Accented: invalid argument. \`output.console\` option is expected to be a boolean. It’s currently set to ${options.output.console}.`);
27
+ }
28
+ }
29
+ if (options.callback !== undefined && typeof options.callback !== 'function') {
30
+ throw new TypeError(`Accented: invalid argument. \`callback\` option must be a function if provided. It’s currently set to ${options.callback}.`);
31
+ }
32
+ if (options.name !== undefined && (typeof options.name !== 'string' || !options.name.match(nameRegex))) {
33
+ 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}.`);
34
+ }
35
+ if (options.axeOptions !== undefined) {
36
+ if (typeof options.axeOptions !== 'object' || options.axeOptions === null) {
37
+ throw new TypeError(`Accented: invalid argument. \`axeOptions\` option must be an object if provided. It’s currently set to ${options.axeOptions}.`);
38
+ }
39
+ const unsupportedKeys = Object.keys(options.axeOptions).filter(key => !(allowedAxeOptions as unknown as Array<string>).includes(key));
40
+ if (unsupportedKeys.length > 0) {
41
+ throw new TypeError(`Accented: invalid argument. \`axeOptions\` contains the following unsupported keys: ${unsupportedKeys.join(', ')}. Valid options are: ${allowedAxeOptions.join(', ')}.`);
42
+ }
43
+ }
44
+ }
@@ -1,3 +0,0 @@
1
- import type { AxeResults } from 'axe-core';
2
- export default function issuesToElements(issues: typeof AxeResults.violations): Element[];
3
- //# sourceMappingURL=issuesToElements.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"issuesToElements.d.ts","sourceRoot":"","sources":["../../src/utils/issuesToElements.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,MAAM,EAAE,OAAO,UAAU,CAAC,UAAU,aAgB5E"}
@@ -1,16 +0,0 @@
1
- export default function issuesToElements(issues) {
2
- const elements = new Set();
3
- for (const issue of issues) {
4
- for (const node of issue.nodes) {
5
- // TODO: how to make this easier / more reliable?
6
- if (typeof node.target[0] === 'string') {
7
- const element = document.querySelector(node.target[0]);
8
- if (element) {
9
- elements.add(element);
10
- }
11
- }
12
- }
13
- }
14
- return [...elements];
15
- }
16
- //# sourceMappingURL=issuesToElements.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"issuesToElements.js","sourceRoot":"","sources":["../../src/utils/issuesToElements.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,MAAoC;IAC3E,MAAM,QAAQ,GAAiB,IAAI,GAAG,EAAE,CAAC;IAEzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC/B,iDAAiD;YACjD,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACvC,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvD,IAAI,OAAO,EAAE,CAAC;oBACZ,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACvB,CAAC"}