accented 0.0.0-20250124142030 → 0.0.0-20250223121749

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 (124) hide show
  1. package/README.md +55 -3
  2. package/dist/accented.d.ts +3 -1
  3. package/dist/accented.d.ts.map +1 -1
  4. package/dist/accented.js +69 -50
  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 -1
  11. package/dist/dom-updater.d.ts.map +1 -1
  12. package/dist/dom-updater.js +26 -19
  13. package/dist/dom-updater.js.map +1 -1
  14. package/dist/elements/{accented-container.d.ts → accented-dialog.d.ts} +10 -4
  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.map +1 -1
  31. package/dist/logger.js +10 -5
  32. package/dist/logger.js.map +1 -1
  33. package/dist/register-elements.d.ts +2 -0
  34. package/dist/register-elements.d.ts.map +1 -0
  35. package/dist/register-elements.js +21 -0
  36. package/dist/register-elements.js.map +1 -0
  37. package/dist/resize-listener.d.ts +2 -0
  38. package/dist/resize-listener.d.ts.map +1 -0
  39. package/dist/resize-listener.js +18 -0
  40. package/dist/resize-listener.js.map +1 -0
  41. package/dist/scanner.d.ts +2 -2
  42. package/dist/scanner.d.ts.map +1 -1
  43. package/dist/scanner.js +97 -33
  44. package/dist/scanner.js.map +1 -1
  45. package/dist/scroll-listeners.d.ts +2 -0
  46. package/dist/scroll-listeners.d.ts.map +1 -0
  47. package/dist/scroll-listeners.js +38 -0
  48. package/dist/scroll-listeners.js.map +1 -0
  49. package/dist/state.d.ts +1 -0
  50. package/dist/state.d.ts.map +1 -1
  51. package/dist/state.js +6 -0
  52. package/dist/state.js.map +1 -1
  53. package/dist/types.d.ts +70 -18
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/types.js +1 -0
  56. package/dist/types.js.map +1 -1
  57. package/dist/utils/deep-merge.js +1 -1
  58. package/dist/utils/deep-merge.js.map +1 -1
  59. package/dist/utils/get-element-html.d.ts +2 -0
  60. package/dist/utils/get-element-html.d.ts.map +1 -0
  61. package/dist/utils/get-element-html.js +14 -0
  62. package/dist/utils/get-element-html.js.map +1 -0
  63. package/dist/utils/get-element-position.d.ts +3 -0
  64. package/dist/utils/get-element-position.d.ts.map +1 -0
  65. package/dist/utils/get-element-position.js +22 -0
  66. package/dist/utils/get-element-position.js.map +1 -0
  67. package/dist/utils/get-scrollable-ancestors.d.ts +2 -0
  68. package/dist/utils/get-scrollable-ancestors.d.ts.map +1 -0
  69. package/dist/utils/get-scrollable-ancestors.js +15 -0
  70. package/dist/utils/get-scrollable-ancestors.js.map +1 -0
  71. package/dist/utils/recalculate-positions.d.ts +2 -0
  72. package/dist/utils/recalculate-positions.d.ts.map +1 -0
  73. package/dist/utils/recalculate-positions.js +27 -0
  74. package/dist/utils/recalculate-positions.js.map +1 -0
  75. package/dist/utils/recalculate-scrollable-ancestors.d.ts +2 -0
  76. package/dist/utils/recalculate-scrollable-ancestors.d.ts.map +1 -0
  77. package/dist/utils/recalculate-scrollable-ancestors.js +13 -0
  78. package/dist/utils/recalculate-scrollable-ancestors.js.map +1 -0
  79. package/dist/utils/supports-anchor-positioning.d.ts +6 -0
  80. package/dist/utils/supports-anchor-positioning.d.ts.map +1 -0
  81. package/dist/utils/supports-anchor-positioning.js +4 -0
  82. package/dist/utils/supports-anchor-positioning.js.map +1 -0
  83. package/dist/utils/transform-violations.d.ts.map +1 -1
  84. package/dist/utils/transform-violations.js +9 -0
  85. package/dist/utils/transform-violations.js.map +1 -1
  86. package/dist/utils/update-elements-with-issues.d.ts +3 -1
  87. package/dist/utils/update-elements-with-issues.d.ts.map +1 -1
  88. package/dist/utils/update-elements-with-issues.js +25 -7
  89. package/dist/utils/update-elements-with-issues.js.map +1 -1
  90. package/dist/validate-options.d.ts +3 -0
  91. package/dist/validate-options.d.ts.map +1 -0
  92. package/dist/validate-options.js +42 -0
  93. package/dist/validate-options.js.map +1 -0
  94. package/package.json +2 -1
  95. package/src/accented.ts +78 -58
  96. package/src/constants.ts +2 -0
  97. package/src/dom-updater.ts +26 -18
  98. package/src/elements/accented-dialog.ts +384 -0
  99. package/src/elements/accented-trigger.ts +179 -0
  100. package/src/intersection-observer.ts +28 -0
  101. package/src/log-and-rethrow.ts +9 -0
  102. package/src/logger.ts +11 -6
  103. package/src/register-elements.ts +21 -0
  104. package/src/resize-listener.ts +17 -0
  105. package/src/scanner.ts +108 -37
  106. package/src/scroll-listeners.ts +37 -0
  107. package/src/state.ts +12 -0
  108. package/src/types.ts +77 -19
  109. package/src/utils/deep-merge.test.ts +7 -0
  110. package/src/utils/deep-merge.ts +1 -1
  111. package/src/utils/get-element-html.ts +13 -0
  112. package/src/utils/get-element-position.ts +21 -0
  113. package/src/utils/get-scrollable-ancestors.ts +14 -0
  114. package/src/utils/recalculate-positions.ts +27 -0
  115. package/src/utils/recalculate-scrollable-ancestors.ts +13 -0
  116. package/src/utils/supports-anchor-positioning.ts +7 -0
  117. package/src/utils/transform-violations.ts +12 -1
  118. package/src/utils/update-elements-with-issues.test.ts +90 -16
  119. package/src/utils/update-elements-with-issues.ts +40 -20
  120. package/src/validate-options.ts +44 -0
  121. package/dist/elements/accented-container.d.ts.map +0 -1
  122. package/dist/elements/accented-container.js +0 -131
  123. package/dist/elements/accented-container.js.map +0 -1
  124. package/src/elements/accented-container.ts +0 -147
@@ -6,11 +6,11 @@ import type { ExtendedElementWithIssues, Issue } from '../types';
6
6
  import updateElementsWithIssues from './update-elements-with-issues';
7
7
 
8
8
  import type { AxeResults, ImpactValue } from 'axe-core';
9
- import type { AccentedContainer } from '../elements/accented-container';
9
+ import type { AccentedTrigger } from '../elements/accented-trigger';
10
10
  type Violation = AxeResults['violations'][number];
11
11
  type Node = Violation['nodes'][number];
12
12
 
13
- const win: Window = {
13
+ const win: Window & { CSS: typeof CSS } = {
14
14
  document: {
15
15
  // @ts-expect-error the return value is of incorrect type.
16
16
  createElement: () => ({
@@ -22,16 +22,35 @@ const win: Window = {
22
22
  },
23
23
  // @ts-expect-error we're missing a lot of properties
24
24
  getComputedStyle: () => ({
25
- zIndex: ''
26
- })
25
+ zIndex: '',
26
+ direction: 'ltr'
27
+ }),
28
+ // @ts-expect-error we're missing a lot of properties
29
+ CSS: {
30
+ supports: () => true
31
+ }
27
32
  }
28
33
 
34
+ const getBoundingClientRect = () => ({});
35
+
36
+ // @ts-expect-error element is not HTMLElement
37
+ const element1: HTMLElement = {getBoundingClientRect, isConnected: true};
29
38
  // @ts-expect-error element is not HTMLElement
30
- const element1: HTMLElement = {};
39
+ const element2: HTMLElement = {getBoundingClientRect, isConnected: true};
31
40
  // @ts-expect-error element is not HTMLElement
32
- const element2: HTMLElement = {};
41
+ const element3: HTMLElement = {getBoundingClientRect, isConnected: false};
42
+
43
+ const trigger = win.document.createElement('accented-trigger') as AccentedTrigger;
44
+
45
+ const position = signal({
46
+ inlineEndLeft: 0,
47
+ blockStartTop: 0,
48
+ direction: 'ltr' as const
49
+ });
33
50
 
34
- const accentedContainer = win.document.createElement('accented-container') as AccentedContainer;
51
+ const visible = signal(true);
52
+
53
+ const scrollableAncestors = signal(new Set<HTMLElement>());
35
54
 
36
55
  const commonNodeProps = {
37
56
  html: '<div></div>',
@@ -51,6 +70,11 @@ const node2: Node = {
51
70
  element: element2,
52
71
  };
53
72
 
73
+ const node3: Node = {
74
+ ...commonNodeProps,
75
+ element: element3,
76
+ };
77
+
54
78
  const commonViolationProps = {
55
79
  help: 'help',
56
80
  helpUrl: 'http://example.com',
@@ -77,6 +101,12 @@ const violation3: Violation = {
77
101
  nodes: [node2]
78
102
  };
79
103
 
104
+ const violation4: Violation = {
105
+ ...commonViolationProps,
106
+ id: 'id4',
107
+ nodes: [node3]
108
+ };
109
+
80
110
  const commonIssueProps = {
81
111
  title: 'help',
82
112
  description: 'description',
@@ -105,13 +135,19 @@ suite('updateElementsWithIssues', () => {
105
135
  {
106
136
  id: 1,
107
137
  element: element1,
108
- accentedContainer,
138
+ position,
139
+ visible,
140
+ trigger,
141
+ scrollableAncestors,
109
142
  issues: signal([issue1])
110
143
  },
111
144
  {
112
145
  id: 2,
113
146
  element: element2,
114
- accentedContainer,
147
+ position,
148
+ visible,
149
+ trigger,
150
+ scrollableAncestors,
115
151
  issues: signal([issue2])
116
152
  }
117
153
  ]);
@@ -128,13 +164,19 @@ suite('updateElementsWithIssues', () => {
128
164
  {
129
165
  id: 1,
130
166
  element: element1,
131
- accentedContainer,
167
+ position,
168
+ visible,
169
+ trigger,
170
+ scrollableAncestors,
132
171
  issues: signal([issue1])
133
172
  },
134
173
  {
135
174
  id: 2,
136
175
  element: element2,
137
- accentedContainer,
176
+ position,
177
+ visible,
178
+ trigger,
179
+ scrollableAncestors,
138
180
  issues: signal([issue2])
139
181
  }
140
182
  ]);
@@ -151,13 +193,19 @@ suite('updateElementsWithIssues', () => {
151
193
  {
152
194
  id: 1,
153
195
  element: element1,
154
- accentedContainer,
196
+ position,
197
+ visible,
198
+ trigger,
199
+ scrollableAncestors,
155
200
  issues: signal([issue1])
156
201
  },
157
202
  {
158
203
  id: 2,
159
204
  element: element2,
160
- accentedContainer,
205
+ position,
206
+ visible,
207
+ trigger,
208
+ scrollableAncestors,
161
209
  issues: signal([issue2, issue3])
162
210
  }
163
211
  ]);
@@ -174,7 +222,10 @@ suite('updateElementsWithIssues', () => {
174
222
  {
175
223
  id: 1,
176
224
  element: element1,
177
- accentedContainer,
225
+ position,
226
+ visible,
227
+ trigger,
228
+ scrollableAncestors,
178
229
  issues: signal([issue1])
179
230
  }
180
231
  ]);
@@ -186,18 +237,41 @@ suite('updateElementsWithIssues', () => {
186
237
  assert.equal(extendedElementsWithIssues.value[1]?.issues.value.length, 1);
187
238
  });
188
239
 
240
+ test('one disconnected element added', () => {
241
+ const extendedElementsWithIssues: Signal<Array<ExtendedElementWithIssues>> = signal([
242
+ {
243
+ id: 1,
244
+ element: element1,
245
+ position,
246
+ visible,
247
+ trigger,
248
+ scrollableAncestors,
249
+ issues: signal([issue1])
250
+ }
251
+ ]);
252
+ updateElementsWithIssues(extendedElementsWithIssues, [violation1, violation4], win, 'accented');
253
+ assert.equal(extendedElementsWithIssues.value.length, 1);
254
+ assert.equal(extendedElementsWithIssues.value[0]?.element, element1);
255
+ });
256
+
189
257
  test('one element removed', () => {
190
258
  const extendedElementsWithIssues: Signal<Array<ExtendedElementWithIssues>> = signal([
191
259
  {
192
260
  id: 1,
193
261
  element: element1,
194
- accentedContainer,
262
+ position,
263
+ visible,
264
+ trigger,
265
+ scrollableAncestors,
195
266
  issues: signal([issue1])
196
267
  },
197
268
  {
198
269
  id: 2,
199
270
  element: element2,
200
- accentedContainer,
271
+ position,
272
+ visible,
273
+ trigger,
274
+ scrollableAncestors,
201
275
  issues: signal([issue2])
202
276
  }
203
277
  ]);
@@ -4,11 +4,15 @@ import { batch, signal } from '@preact/signals-core';
4
4
  import type { ExtendedElementWithIssues } from '../types';
5
5
  import transformViolations from './transform-violations.js';
6
6
  import areIssueSetsEqual from './are-issue-sets-equal.js';
7
- import type { AccentedContainer } from '../elements/accented-container';
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';
8
12
 
9
13
  let count = 0;
10
14
 
11
- export default function updateElementsWithIssues(extendedElementsWithIssues: Signal<Array<ExtendedElementWithIssues>>, violations: typeof AxeResults.violations, win: Window, name: string) {
15
+ export default function updateElementsWithIssues(extendedElementsWithIssues: Signal<Array<ExtendedElementWithIssues>>, violations: typeof AxeResults.violations, win: Window & { CSS: typeof CSS }, name: string) {
12
16
  const updatedElementsWithIssues = transformViolations(violations);
13
17
 
14
18
  batch(() => {
@@ -32,24 +36,40 @@ export default function updateElementsWithIssues(extendedElementsWithIssues: Sig
32
36
  .filter(extendedElementWithIssues => {
33
37
  return !removedElementsWithIssues.some(removedElementWithIssues => removedElementWithIssues.element === extendedElementWithIssues.element);
34
38
  })
35
- .concat(addedElementsWithIssues.map(addedElementWithIssues => {
36
- const id = count++;
37
- const accentedContainer = win.document.createElement(`${name}-container`) as AccentedContainer;
38
- const elementZIndex = parseInt(win.getComputedStyle(addedElementWithIssues.element).zIndex, 10);
39
- if (!isNaN(elementZIndex)) {
40
- accentedContainer.style.setProperty('z-index', (elementZIndex + 1).toString());
41
- }
42
- accentedContainer.style.setProperty('position-anchor', `--${name}-anchor-${id}`);
43
- accentedContainer.dataset.id = id.toString();
44
- const issues = signal(addedElementWithIssues.issues);
45
- accentedContainer.issues = issues;
46
- return {
47
- id,
48
- element: addedElementWithIssues.element,
49
- accentedContainer,
50
- issues
51
- };
52
- }));
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
+ );
53
73
  }
54
74
  });
55
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 +0,0 @@
1
- {"version":3,"file":"accented-container.d.ts","sourceRoot":"","sources":["../../src/elements/accented-container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC;CAC1C;+BAIqB,MAAM;;iCAkEN,eAAe,GAAG,SAAS;iCAE3B,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS;gBAElC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAtE5C,wBAwIE"}
@@ -1,131 +0,0 @@
1
- import { effect } from '@preact/signals-core';
2
- // We want Accented to not throw an error in Node, and use static imports,
3
- // so we can't export `class extends HTMLElement` because HTMLElement is not available in Node.
4
- export default (name) => {
5
- const containerTemplate = document.createElement('template');
6
- containerTemplate.innerHTML = `
7
- <button id="trigger">⚠</button>
8
- <dialog dir="ltr" aria-labelledby="title">
9
- <h2 id="title">Issues</h2>
10
- <ul id="issues"></ul>
11
- </dialog>
12
- `;
13
- const issueTemplate = document.createElement('template');
14
- issueTemplate.innerHTML = `
15
- <li>
16
- <a></a>
17
- <div></div>
18
- </li>
19
- `;
20
- const descriptionTemplate = document.createElement('template');
21
- descriptionTemplate.innerHTML = `
22
- <span></span>
23
- <ul></ul>
24
- `;
25
- const stylesheet = new CSSStyleSheet();
26
- stylesheet.replaceSync(`
27
- :host {
28
- position: absolute;
29
- inset-inline-end: anchor(end);
30
- inset-block-end: anchor(end);
31
-
32
- /* Popover-specific stuff */
33
- border: none;
34
- padding: 0;
35
- margin-inline-end: 0;
36
- margin-block-end: 0;
37
- }
38
-
39
- #trigger {
40
- box-sizing: border-box;
41
- font-size: 1rem;
42
- inline-size: max(32px, 2rem);
43
- block-size: max(32px, 2rem);
44
-
45
- /* Make it look better in forced-colors mode, */
46
- border: 2px solid transparent;
47
-
48
- background-color: var(--${name}-primary-color);
49
- color: var(--${name}-secondary-color);
50
-
51
- outline-offset: -4px;
52
- outline-color: var(--${name}-secondary-color);
53
-
54
- &:focus-visible {
55
- outline-width: 2px;
56
- outline-style: solid;
57
- }
58
-
59
- &:hover:not(:focus-visible) {
60
- outline-width: 2px;
61
- outline-style: dashed;
62
- }
63
- }
64
- `);
65
- return class AccentedContainerLocal extends HTMLElement {
66
- #abortController;
67
- #disposeOfEffect;
68
- issues;
69
- constructor() {
70
- super();
71
- this.attachShadow({ mode: 'open' });
72
- const content = containerTemplate.content.cloneNode(true);
73
- if (this.shadowRoot) {
74
- this.shadowRoot.adoptedStyleSheets.push(stylesheet);
75
- this.shadowRoot.append(content);
76
- }
77
- }
78
- connectedCallback() {
79
- if (this.shadowRoot) {
80
- const { shadowRoot } = this;
81
- const trigger = shadowRoot.getElementById('trigger');
82
- const dialog = shadowRoot.querySelector('dialog');
83
- this.#abortController = new AbortController();
84
- trigger?.addEventListener('click', () => {
85
- dialog?.showModal();
86
- }, { signal: this.#abortController.signal });
87
- this.#disposeOfEffect = effect(() => {
88
- if (this.issues) {
89
- const issues = this.issues.value;
90
- const issuesList = shadowRoot.getElementById('issues');
91
- if (issuesList) {
92
- issuesList.innerHTML = '';
93
- for (const issue of issues) {
94
- const issueContent = issueTemplate.content.cloneNode(true);
95
- const a = issueContent.querySelector('a');
96
- const div = issueContent.querySelector('div');
97
- if (a && div) {
98
- a.textContent = issue.title;
99
- a.href = issue.url;
100
- const descriptionItems = issue.description.split(/\n\s*/);
101
- const descriptionContent = descriptionTemplate.content.cloneNode(true);
102
- const descriptionTitle = descriptionContent.querySelector('span');
103
- const descriptionList = descriptionContent.querySelector('ul');
104
- if (descriptionTitle && descriptionList && descriptionItems.length > 1) {
105
- descriptionTitle.textContent = descriptionItems[0];
106
- for (const descriptionItem of descriptionItems.slice(1)) {
107
- const li = document.createElement('li');
108
- li.textContent = descriptionItem;
109
- descriptionList.appendChild(li);
110
- }
111
- div.appendChild(descriptionContent);
112
- }
113
- }
114
- issuesList.appendChild(issueContent);
115
- }
116
- }
117
- }
118
- });
119
- }
120
- }
121
- disconnectedCallback() {
122
- if (this.#abortController) {
123
- this.#abortController.abort();
124
- }
125
- if (this.#disposeOfEffect) {
126
- this.#disposeOfEffect();
127
- }
128
- }
129
- };
130
- };
131
- //# sourceMappingURL=accented-container.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"accented-container.js","sourceRoot":"","sources":["../../src/elements/accented-container.ts"],"names":[],"mappings":"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"}
@@ -1,147 +0,0 @@
1
- import type { Issue } from '../types';
2
- import type { Signal } from '@preact/signals-core';
3
- import { effect } from '@preact/signals-core';
4
-
5
- export interface AccentedContainer extends HTMLElement {
6
- issues: Signal<Array<Issue>> | undefined;
7
- }
8
-
9
- // We want Accented to not throw an error in Node, and use static imports,
10
- // so we can't export `class extends HTMLElement` because HTMLElement is not available in Node.
11
- export default (name: string) => {
12
- const containerTemplate = document.createElement('template');
13
- containerTemplate.innerHTML = `
14
- <button id="trigger">⚠</button>
15
- <dialog dir="ltr" aria-labelledby="title">
16
- <h2 id="title">Issues</h2>
17
- <ul id="issues"></ul>
18
- </dialog>
19
- `;
20
-
21
- const issueTemplate = document.createElement('template');
22
- issueTemplate.innerHTML = `
23
- <li>
24
- <a></a>
25
- <div></div>
26
- </li>
27
- `;
28
-
29
- const descriptionTemplate = document.createElement('template');
30
- descriptionTemplate.innerHTML = `
31
- <span></span>
32
- <ul></ul>
33
- `;
34
-
35
- const stylesheet = new CSSStyleSheet();
36
- stylesheet.replaceSync(`
37
- :host {
38
- position: absolute;
39
- inset-inline-end: anchor(end);
40
- inset-block-end: anchor(end);
41
-
42
- /* Popover-specific stuff */
43
- border: none;
44
- padding: 0;
45
- margin-inline-end: 0;
46
- margin-block-end: 0;
47
- }
48
-
49
- #trigger {
50
- box-sizing: border-box;
51
- font-size: 1rem;
52
- inline-size: max(32px, 2rem);
53
- block-size: max(32px, 2rem);
54
-
55
- /* Make it look better in forced-colors mode, */
56
- border: 2px solid transparent;
57
-
58
- background-color: var(--${name}-primary-color);
59
- color: var(--${name}-secondary-color);
60
-
61
- outline-offset: -4px;
62
- outline-color: var(--${name}-secondary-color);
63
-
64
- &:focus-visible {
65
- outline-width: 2px;
66
- outline-style: solid;
67
- }
68
-
69
- &:hover:not(:focus-visible) {
70
- outline-width: 2px;
71
- outline-style: dashed;
72
- }
73
- }
74
- `);
75
-
76
- return class AccentedContainerLocal extends HTMLElement implements AccentedContainer {
77
- #abortController: AbortController | undefined;
78
-
79
- #disposeOfEffect: (() => void) | undefined;
80
-
81
- issues: Signal<Array<Issue>> | undefined;
82
-
83
- constructor() {
84
- super();
85
- this.attachShadow({ mode: 'open' });
86
- const content = containerTemplate.content.cloneNode(true);
87
- if (this.shadowRoot) {
88
- this.shadowRoot.adoptedStyleSheets.push(stylesheet);
89
- this.shadowRoot.append(content);
90
- }
91
- }
92
-
93
- connectedCallback() {
94
- if (this.shadowRoot) {
95
- const { shadowRoot } = this;
96
- const trigger = shadowRoot.getElementById('trigger');
97
- const dialog = shadowRoot.querySelector('dialog');
98
- this.#abortController = new AbortController();
99
- trigger?.addEventListener('click', () => {
100
- dialog?.showModal();
101
- }, { signal: this.#abortController.signal });
102
-
103
- this.#disposeOfEffect = effect(() => {
104
- if (this.issues) {
105
- const issues = this.issues.value;
106
- const issuesList = shadowRoot.getElementById('issues');
107
- if (issuesList) {
108
- issuesList.innerHTML = '';
109
- for (const issue of issues) {
110
- const issueContent = issueTemplate.content.cloneNode(true) as Element;
111
- const a = issueContent.querySelector('a');
112
- const div = issueContent.querySelector('div');
113
- if (a && div) {
114
- a.textContent = issue.title;
115
- a.href = issue.url;
116
- const descriptionItems = issue.description.split(/\n\s*/);
117
- const descriptionContent = descriptionTemplate.content.cloneNode(true) as Element;
118
- const descriptionTitle = descriptionContent.querySelector('span');
119
- const descriptionList = descriptionContent.querySelector('ul');
120
- if (descriptionTitle && descriptionList && descriptionItems.length > 1) {
121
- descriptionTitle.textContent = descriptionItems[0]!;
122
- for (const descriptionItem of descriptionItems.slice(1)) {
123
- const li = document.createElement('li');
124
- li.textContent = descriptionItem;
125
- descriptionList.appendChild(li);
126
- }
127
- div.appendChild(descriptionContent);
128
- }
129
- }
130
- issuesList.appendChild(issueContent);
131
- }
132
- }
133
- }
134
- });
135
- }
136
- }
137
-
138
- disconnectedCallback() {
139
- if (this.#abortController) {
140
- this.#abortController.abort();
141
- }
142
- if (this.#disposeOfEffect) {
143
- this.#disposeOfEffect();
144
- }
145
- }
146
- };
147
- };