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.
- package/README.md +55 -3
- package/dist/accented.d.ts +3 -1
- package/dist/accented.d.ts.map +1 -1
- package/dist/accented.js +69 -50
- package/dist/accented.js.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +3 -0
- package/dist/constants.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 +26 -19
- package/dist/dom-updater.js.map +1 -1
- package/dist/elements/{accented-container.d.ts → accented-dialog.d.ts} +10 -4
- package/dist/elements/accented-dialog.d.ts.map +1 -0
- package/dist/elements/accented-dialog.js +361 -0
- package/dist/elements/accented-dialog.js.map +1 -0
- package/dist/elements/accented-trigger.d.ts +359 -0
- package/dist/elements/accented-trigger.d.ts.map +1 -0
- package/dist/elements/accented-trigger.js +159 -0
- package/dist/elements/accented-trigger.js.map +1 -0
- package/dist/intersection-observer.d.ts +5 -0
- package/dist/intersection-observer.d.ts.map +1 -0
- package/dist/intersection-observer.js +28 -0
- package/dist/intersection-observer.js.map +1 -0
- package/dist/log-and-rethrow.d.ts +2 -0
- package/dist/log-and-rethrow.d.ts.map +1 -0
- package/dist/log-and-rethrow.js +7 -0
- package/dist/log-and-rethrow.js.map +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +10 -5
- package/dist/logger.js.map +1 -1
- package/dist/register-elements.d.ts +2 -0
- package/dist/register-elements.d.ts.map +1 -0
- package/dist/register-elements.js +21 -0
- package/dist/register-elements.js.map +1 -0
- package/dist/resize-listener.d.ts +2 -0
- package/dist/resize-listener.d.ts.map +1 -0
- package/dist/resize-listener.js +18 -0
- package/dist/resize-listener.js.map +1 -0
- package/dist/scanner.d.ts +2 -2
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +97 -33
- package/dist/scanner.js.map +1 -1
- package/dist/scroll-listeners.d.ts +2 -0
- package/dist/scroll-listeners.d.ts.map +1 -0
- package/dist/scroll-listeners.js +38 -0
- package/dist/scroll-listeners.js.map +1 -0
- package/dist/state.d.ts +1 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +6 -0
- package/dist/state.js.map +1 -1
- package/dist/types.d.ts +70 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/deep-merge.js +1 -1
- package/dist/utils/deep-merge.js.map +1 -1
- package/dist/utils/get-element-html.d.ts +2 -0
- package/dist/utils/get-element-html.d.ts.map +1 -0
- package/dist/utils/get-element-html.js +14 -0
- package/dist/utils/get-element-html.js.map +1 -0
- package/dist/utils/get-element-position.d.ts +3 -0
- package/dist/utils/get-element-position.d.ts.map +1 -0
- package/dist/utils/get-element-position.js +22 -0
- package/dist/utils/get-element-position.js.map +1 -0
- package/dist/utils/get-scrollable-ancestors.d.ts +2 -0
- package/dist/utils/get-scrollable-ancestors.d.ts.map +1 -0
- package/dist/utils/get-scrollable-ancestors.js +15 -0
- package/dist/utils/get-scrollable-ancestors.js.map +1 -0
- package/dist/utils/recalculate-positions.d.ts +2 -0
- package/dist/utils/recalculate-positions.d.ts.map +1 -0
- package/dist/utils/recalculate-positions.js +27 -0
- package/dist/utils/recalculate-positions.js.map +1 -0
- package/dist/utils/recalculate-scrollable-ancestors.d.ts +2 -0
- package/dist/utils/recalculate-scrollable-ancestors.d.ts.map +1 -0
- package/dist/utils/recalculate-scrollable-ancestors.js +13 -0
- package/dist/utils/recalculate-scrollable-ancestors.js.map +1 -0
- package/dist/utils/supports-anchor-positioning.d.ts +6 -0
- package/dist/utils/supports-anchor-positioning.d.ts.map +1 -0
- package/dist/utils/supports-anchor-positioning.js +4 -0
- package/dist/utils/supports-anchor-positioning.js.map +1 -0
- package/dist/utils/transform-violations.d.ts.map +1 -1
- package/dist/utils/transform-violations.js +9 -0
- package/dist/utils/transform-violations.js.map +1 -1
- package/dist/utils/update-elements-with-issues.d.ts +3 -1
- package/dist/utils/update-elements-with-issues.d.ts.map +1 -1
- package/dist/utils/update-elements-with-issues.js +25 -7
- package/dist/utils/update-elements-with-issues.js.map +1 -1
- package/dist/validate-options.d.ts +3 -0
- package/dist/validate-options.d.ts.map +1 -0
- package/dist/validate-options.js +42 -0
- package/dist/validate-options.js.map +1 -0
- package/package.json +2 -1
- package/src/accented.ts +78 -58
- package/src/constants.ts +2 -0
- package/src/dom-updater.ts +26 -18
- package/src/elements/accented-dialog.ts +384 -0
- package/src/elements/accented-trigger.ts +179 -0
- package/src/intersection-observer.ts +28 -0
- package/src/log-and-rethrow.ts +9 -0
- package/src/logger.ts +11 -6
- package/src/register-elements.ts +21 -0
- package/src/resize-listener.ts +17 -0
- package/src/scanner.ts +108 -37
- package/src/scroll-listeners.ts +37 -0
- package/src/state.ts +12 -0
- package/src/types.ts +77 -19
- package/src/utils/deep-merge.test.ts +7 -0
- package/src/utils/deep-merge.ts +1 -1
- package/src/utils/get-element-html.ts +13 -0
- package/src/utils/get-element-position.ts +21 -0
- package/src/utils/get-scrollable-ancestors.ts +14 -0
- package/src/utils/recalculate-positions.ts +27 -0
- package/src/utils/recalculate-scrollable-ancestors.ts +13 -0
- package/src/utils/supports-anchor-positioning.ts +7 -0
- package/src/utils/transform-violations.ts +12 -1
- package/src/utils/update-elements-with-issues.test.ts +90 -16
- package/src/utils/update-elements-with-issues.ts +40 -20
- package/src/validate-options.ts +44 -0
- package/dist/elements/accented-container.d.ts.map +0 -1
- package/dist/elements/accented-container.js +0 -131
- package/dist/elements/accented-container.js.map +0 -1
- 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 {
|
|
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
|
|
39
|
+
const element2: HTMLElement = {getBoundingClientRect, isConnected: true};
|
|
31
40
|
// @ts-expect-error element is not HTMLElement
|
|
32
|
-
const
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
};
|