@issuegraph/editor 0.3.0 → 0.10.0

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 (87) hide show
  1. package/README.md +31 -6
  2. package/dist/a11y/baseline.d.ts +182 -0
  3. package/dist/a11y/baseline.d.ts.map +1 -0
  4. package/dist/a11y/baseline.js +430 -0
  5. package/dist/a11y/baseline.js.map +1 -0
  6. package/dist/audit/styles.d.ts +1 -1
  7. package/dist/audit/styles.d.ts.map +1 -1
  8. package/dist/audit/styles.js +1 -1
  9. package/dist/create/draft.d.ts +17 -0
  10. package/dist/create/draft.d.ts.map +1 -1
  11. package/dist/create/draft.js +19 -0
  12. package/dist/create/draft.js.map +1 -1
  13. package/dist/create/keys.d.ts +70 -5
  14. package/dist/create/keys.d.ts.map +1 -1
  15. package/dist/create/keys.js +78 -17
  16. package/dist/create/keys.js.map +1 -1
  17. package/dist/firstpass/candidates.d.ts +17 -1
  18. package/dist/firstpass/candidates.d.ts.map +1 -1
  19. package/dist/index.d.ts +6 -4
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +12 -2
  22. package/dist/index.js.map +1 -1
  23. package/dist/overlay/render.d.ts.map +1 -1
  24. package/dist/overlay/render.js +54 -14
  25. package/dist/overlay/render.js.map +1 -1
  26. package/dist/overlay/styles.d.ts +1 -1
  27. package/dist/overlay/styles.d.ts.map +1 -1
  28. package/dist/overlay/styles.js +40 -0
  29. package/dist/overlay/styles.js.map +1 -1
  30. package/dist/picker/render.d.ts +26 -16
  31. package/dist/picker/render.d.ts.map +1 -1
  32. package/dist/picker/render.js +25 -36
  33. package/dist/picker/render.js.map +1 -1
  34. package/dist/picker/styles.d.ts +7 -7
  35. package/dist/picker/styles.d.ts.map +1 -1
  36. package/dist/picker/styles.js +7 -36
  37. package/dist/picker/styles.js.map +1 -1
  38. package/dist/picker/view.d.ts +8 -4
  39. package/dist/picker/view.d.ts.map +1 -1
  40. package/dist/picker/view.js +4 -3
  41. package/dist/picker/view.js.map +1 -1
  42. package/dist/picker/words.d.ts +12 -10
  43. package/dist/picker/words.d.ts.map +1 -1
  44. package/dist/picker/words.js +12 -8
  45. package/dist/picker/words.js.map +1 -1
  46. package/dist/scale/ladder.d.ts.map +1 -1
  47. package/dist/scale/ladder.js +10 -0
  48. package/dist/scale/ladder.js.map +1 -1
  49. package/dist/scale/render.d.ts.map +1 -1
  50. package/dist/scale/render.js +9 -1
  51. package/dist/scale/render.js.map +1 -1
  52. package/dist/workspace/chrome.d.ts +1 -1
  53. package/dist/workspace/chrome.d.ts.map +1 -1
  54. package/dist/workspace/chrome.js +48 -0
  55. package/dist/workspace/chrome.js.map +1 -1
  56. package/dist/workspace/firstpass.d.ts +166 -0
  57. package/dist/workspace/firstpass.d.ts.map +1 -0
  58. package/dist/workspace/firstpass.js +151 -0
  59. package/dist/workspace/firstpass.js.map +1 -0
  60. package/dist/workspace/host.d.ts +212 -10
  61. package/dist/workspace/host.d.ts.map +1 -1
  62. package/dist/workspace/host.js +434 -42
  63. package/dist/workspace/host.js.map +1 -1
  64. package/dist/workspace/inspector.d.ts +45 -1
  65. package/dist/workspace/inspector.d.ts.map +1 -1
  66. package/dist/workspace/inspector.js +11 -0
  67. package/dist/workspace/inspector.js.map +1 -1
  68. package/dist/workspace/mount.d.ts +52 -5
  69. package/dist/workspace/mount.d.ts.map +1 -1
  70. package/dist/workspace/mount.js +1391 -56
  71. package/dist/workspace/mount.js.map +1 -1
  72. package/dist/workspace/rail.d.ts.map +1 -1
  73. package/dist/workspace/rail.js +12 -0
  74. package/dist/workspace/rail.js.map +1 -1
  75. package/dist/workspace/recovery.d.ts +155 -0
  76. package/dist/workspace/recovery.d.ts.map +1 -0
  77. package/dist/workspace/recovery.js +156 -0
  78. package/dist/workspace/recovery.js.map +1 -0
  79. package/dist/workspace/render.d.ts +402 -1
  80. package/dist/workspace/render.d.ts.map +1 -1
  81. package/dist/workspace/render.js +947 -36
  82. package/dist/workspace/render.js.map +1 -1
  83. package/dist/workspace/styles.d.ts +1 -1
  84. package/dist/workspace/styles.d.ts.map +1 -1
  85. package/dist/workspace/styles.js +554 -41
  86. package/dist/workspace/styles.js.map +1 -1
  87. package/package.json +3 -3
@@ -0,0 +1,430 @@
1
+ /**
2
+ * The accessible contract of every command control, read off a rendered
3
+ * surface — so it is committed as an artifact rather than asserted in prose.
4
+ *
5
+ * ## Why a DOM node and not an `ElementSpec`
6
+ *
7
+ * There is no spec tree for the workspace to walk. `renderWorkspace` returns
8
+ * `markup: string`; it composes its four zones by joining independently
9
+ * rendered strings, the `data-zone` wrapper is the one tag written by hand in
10
+ * that file, and every `…Spec` builder is module-private. Worse for a spec
11
+ * walk, a substantial part of the interactive surface never passes a renderer
12
+ * at all — `mountWorkspace` builds the kind chooser, the target search and its
13
+ * match list with `createElement`, and says so ("WHAT IS LEFT HERE IS WHAT
14
+ * NEEDS A DOM"). A baseline taken over specs would silently omit exactly the
15
+ * keyboard-relevant controls.
16
+ *
17
+ * The rendered DOM has all of it, and it is also what a screen reader actually
18
+ * meets.
19
+ *
20
+ * ## NOT EXPORTED, and that is the correction of a real mistake
21
+ *
22
+ * An earlier revision published `controlSurface` on the package surface,
23
+ * reasoning that a host composing these zones into its own chrome would want
24
+ * the same record. Nothing asked for it, and `index.ts` states the rule it
25
+ * broke: "a published package can add an export later and can never take one
26
+ * back, so nothing is exported before something is owed."
27
+ *
28
+ * The cost was not theoretical. Exporting it turned this file into a
29
+ * general-purpose accessible-name and focusability reader, and accessible-name
30
+ * computation has a long tail — `title`, `placeholder`, an input's own `value`,
31
+ * whitespace-only labels, hidden inputs, `contenteditable`. Three consecutive
32
+ * review rounds produced findings of exactly that shape: each real, each cheap,
33
+ * and none about markup this package draws. That tail has no end, and this
34
+ * change cannot discharge it.
35
+ *
36
+ * Internal, the obligation is bounded and discharged: the reader only ever
37
+ * meets what this package renders, which is a closed set recorded in six
38
+ * states. If a host ever owes this, export it then — with its tail addressed,
39
+ * and against a consumer that actually needs it.
40
+ *
41
+ * ## Structurally typed, so this module still touches no global
42
+ *
43
+ * {@link SurfaceElement} is declared by what it must answer rather than as
44
+ * `Element`, which is `element.ts`'s own `SpecDocument` idiom — "declared
45
+ * structurally rather than as `Document` so a host can pass any implementation
46
+ * that answers these five calls, and so this module stays honest about how
47
+ * little of the DOM it actually needs". `purity.test.ts` imports every shipped
48
+ * module with the browser globals removed; nothing here reaches for one.
49
+ *
50
+ * ## What is recorded, and what is deliberately not
51
+ *
52
+ * VALUES ARE KEPT FOR MACHINE STATES AND DROPPED FOR HUMAN-READABLE NAMES.
53
+ * That split is by provenance, not one blanket rule, because the two fail
54
+ * differently. `aria-pressed` is rendered as `cond ? 'true' : 'false'`, so a
55
+ * baseline holding only the attribute NAME is byte-identical when a toggle
56
+ * inverts — the regression it exists to catch. A label, meanwhile, is often
57
+ * the host's word (`picker/words.ts`, `reevaluate/words.ts` and
58
+ * `firstpass/words.ts` all require a `Record<K, string>` from the host and
59
+ * default none), so pinning the string would fail any host that translated it.
60
+ *
61
+ * An earlier draft justified dropping every value with "the package ships no
62
+ * English", which is false: `scale/render.ts` writes `'connected components'`,
63
+ * `'what to do next'`, `'search matches'` and `'isolated issues'` itself, and
64
+ * the viewer ships more landmark names. The true, narrower claim is the one
65
+ * above.
66
+ *
67
+ * AN IDREF IS RECORDED BY WHETHER IT RESOLVES, never by its value. The
68
+ * disclosure's `aria-controls` names `diffRegionId(recovery.mutationId)`, and a
69
+ * mutation id is generated per run — pinning it would make the artifact churn
70
+ * on every render for no signal. What is worth pinning is the fact a reader
71
+ * depends on: that the id names a region that is actually there. A dangling
72
+ * `aria-controls` is a real defect and a stable one to record.
73
+ */
74
+ /**
75
+ * Every attribute a control publishes itself on.
76
+ *
77
+ * THREE CHANNELS, NOT ONE, and reading only the first is how a record comes to
78
+ * claim a surface it never saw. `data-ig-command` is the general one, but the
79
+ * first pass's y/n/s answers carry `data-ig-answer` and the audit header's
80
+ * toggle carries `data-ig-audit-filter` — `firstpass/render.ts` and
81
+ * `audit/surface.ts` each say so where they declare theirs. Keyed on the
82
+ * command alone, this would have recorded `null` for the audit toggle and for
83
+ * every answer, and the rules below would have skipped exactly the controls a
84
+ * keyboard reader depends on most.
85
+ */
86
+ export const CONTROL_ATTRIBUTES = Object.freeze([
87
+ 'data-ig-command',
88
+ 'data-ig-answer',
89
+ 'data-ig-audit-filter',
90
+ ]);
91
+ /**
92
+ * Implicit roles, for the tags this package actually renders.
93
+ *
94
+ * Closed and small on purpose. A general HTML-AAM table would be a second
95
+ * implementation of a specification this package does not own, and every entry
96
+ * beyond what is rendered here would be untested. An unmapped tag records
97
+ * `null` rather than a guess — including everything in the SVG namespace,
98
+ * where the HTML implicit roles do not apply and `path` has none at all.
99
+ */
100
+ const IMPLICIT_ROLES = Object.freeze({
101
+ button: 'button',
102
+ h1: 'heading',
103
+ h2: 'heading',
104
+ h3: 'heading',
105
+ h4: 'heading',
106
+ li: 'listitem',
107
+ ol: 'list',
108
+ ul: 'list',
109
+ });
110
+ /**
111
+ * The two tags whose implicit role depends on more than the tag.
112
+ *
113
+ * `a` is a `link` only with an `href` — without one it is not a link and not
114
+ * focusable. `section` is a `region` only when it has an accessible name;
115
+ * unnamed it exposes no role at all. Both were mapped unconditionally in an
116
+ * earlier revision, which recorded a role the accessibility tree does not have.
117
+ */
118
+ /**
119
+ * `input`'s implicit role, which is its `type`'s rather than its tag's.
120
+ *
121
+ * The mounted target search is `<input type="search">` — `searchbox`, not
122
+ * nothing — and recording `null` for a control this package itself renders
123
+ * means the role column could not notice it being changed into a semantically
124
+ * different control. Only the types rendered here are mapped; the rest stay
125
+ * `null`, on the same rule as every other unmapped tag.
126
+ */
127
+ const INPUT_ROLES = Object.freeze({
128
+ button: 'button',
129
+ checkbox: 'checkbox',
130
+ radio: 'radio',
131
+ reset: 'button',
132
+ search: 'searchbox',
133
+ submit: 'button',
134
+ text: 'textbox',
135
+ });
136
+ function conditionalRole(root, element, tag) {
137
+ if (tag === 'a')
138
+ return element.getAttribute('href') === null ? null : 'link';
139
+ if (tag === 'section')
140
+ return nameSource(root, element) === 'none' ? null : 'region';
141
+ // NO `type` IS `type="text"`, which is HTML's own default rather than an
142
+ // assumption: an `<input>` with no type is a text field.
143
+ if (tag === 'input')
144
+ return INPUT_ROLES[element.getAttribute('type') ?? 'text'] ?? null;
145
+ return null;
146
+ }
147
+ /** ARIA attributes whose value is drawn from a fixed set, so the value is data. */
148
+ const ENUMERATED_ARIA = Object.freeze([
149
+ 'aria-busy',
150
+ 'aria-checked',
151
+ 'aria-current',
152
+ 'aria-expanded',
153
+ 'aria-hidden',
154
+ 'aria-live',
155
+ 'aria-modal',
156
+ 'aria-pressed',
157
+ 'aria-selected',
158
+ ]);
159
+ /** ARIA attributes whose value is an id, recorded by whether it resolves. */
160
+ const IDREF_ARIA = Object.freeze([
161
+ 'aria-controls',
162
+ 'aria-describedby',
163
+ 'aria-labelledby',
164
+ ]);
165
+ const TEXT_NODE = 3;
166
+ function isElement(node) {
167
+ return 'tagName' in node;
168
+ }
169
+ /**
170
+ * The text a screen reader would announce for this element.
171
+ *
172
+ * SUBTREES MARKED `aria-hidden` CONTRIBUTE NOTHING, which is the case a naive
173
+ * "does it have a text child" test gets wrong. `parts.ts` renders a command
174
+ * button as a hidden glyph beside its label; delete the label and the button
175
+ * still has a text descendant while its accessible name is empty. That is a
176
+ * name loss no presence check would report.
177
+ */
178
+ function visibleText(element) {
179
+ let out = '';
180
+ const walk = (node) => {
181
+ if (!isElement(node)) {
182
+ if (node.nodeType === TEXT_NODE)
183
+ out += node.nodeValue ?? '';
184
+ return;
185
+ }
186
+ // `hidden` AS WELL AS `aria-hidden`, and for the same reason one step
187
+ // further along: a natively hidden subtree is not rendered at all, so its
188
+ // text reaches no reader. `<button><span hidden>Save</span></button>` is
189
+ // exposed with NO accessible name, and counting that text reported one —
190
+ // letting the naming rule pass on a control that announces nothing.
191
+ if (node.getAttribute('aria-hidden') === 'true')
192
+ return;
193
+ if (node.getAttribute('hidden') !== null)
194
+ return;
195
+ for (let index = 0; index < node.childNodes.length; index += 1) {
196
+ const child = node.childNodes[index];
197
+ if (child !== undefined)
198
+ walk(child);
199
+ }
200
+ };
201
+ walk(element);
202
+ return out.trim();
203
+ }
204
+ /**
205
+ * Whether a `<label>` names this control, by either association HTML defines.
206
+ *
207
+ * WRAPPING FIRST, then `for`. `scale/render.ts` uses the wrapping form and says
208
+ * why in as many words — two search boxes side by side with one `id` would make
209
+ * `for` resolve to whichever came first, so one would silently lose its label.
210
+ *
211
+ * THE `for` LOOKUP WALKS AND COMPARES rather than building `label[for="..."]`:
212
+ * an id is host data, and interpolating one into a selector is the injection
213
+ * this module already had to remove once.
214
+ */
215
+ function labelNames(root, element) {
216
+ const wrapping = element.closest('label');
217
+ if (wrapping !== null && visibleText(wrapping) !== '')
218
+ return true;
219
+ const id = element.getAttribute('id');
220
+ if (id === null || id === '')
221
+ return false;
222
+ for (const label of root.querySelectorAll('label')) {
223
+ if (label.getAttribute('for') === id && visibleText(label) !== '')
224
+ return true;
225
+ }
226
+ return false;
227
+ }
228
+ function nameSource(root, element) {
229
+ // AN EMPTY VALUE IS NOT A NAME, and it is not the same as no attribute.
230
+ // `renderMarkup` omits only `undefined`, `null` and `false`, so
231
+ // `aria-label=""` does reach the markup — the case the "omitted, never empty"
232
+ // rule `holdLine` states for `data-code` exists to prevent.
233
+ // `aria-labelledby` FIRST, because accessible-name computation resolves it
234
+ // BEFORE `aria-label` — so a host supplying both, with the reference pointing
235
+ // at an empty element, is exposed with no name while a reader that took the
236
+ // label would have reported one. Order is the whole of the fix; each branch
237
+ // was already right on its own.
238
+ //
239
+ // AN IDREF THAT RESOLVES IS NOT YET A NAME. `aria-labelledby` naming an
240
+ // element that exists but carries no text computes to an empty accessible
241
+ // name, and reading the attribute alone reported a supplied name for a
242
+ // control that announces nothing. This is the same defect as `aria-label=""`,
243
+ // which is already answered `empty` — fixing one half and not the other
244
+ // would have left the rule inconsistent about the same mistake.
245
+ //
246
+ // `ariaOf` keeps answering `resolves` for the same attribute, and the two are
247
+ // not in conflict: it reports whether the reference POINTS at something,
248
+ // which is its own defect when it does not. Whether the thing it points at
249
+ // says anything is this function's question.
250
+ const labelledBy = element.getAttribute('aria-labelledby');
251
+ if (labelledBy !== null) {
252
+ const named = labelledBy.split(/\s+/).filter((token) => token !== '');
253
+ let text = '';
254
+ for (const target of root.querySelectorAll('[id]')) {
255
+ if (named.includes(target.getAttribute('id') ?? ''))
256
+ text += visibleText(target);
257
+ }
258
+ return text.trim() === '' ? 'empty' : 'aria-labelledby';
259
+ }
260
+ const label = element.getAttribute('aria-label');
261
+ // TRIMMED, because a name made of spaces is not a name: the browser exposes
262
+ // an empty accessible name for `aria-label=" "`, which a template padding an
263
+ // empty translation produces easily.
264
+ if (label !== null)
265
+ return label.trim() === '' ? 'empty' : 'aria-label';
266
+ if (visibleText(element) !== '')
267
+ return 'text';
268
+ return labelNames(root, element) ? 'label' : 'none';
269
+ }
270
+ function tabStopOf(element) {
271
+ // DISABLED AND INERT ARE NOT TAB STOPS, whatever the tag says. The mount sets
272
+ // `inert` on every zone while the first-pass overlay is up — "the zones go
273
+ // inert under it" — so without this every covered control recorded `tab` and
274
+ // passed a rule asserting the keyboard can reach it, while the browser was
275
+ // refusing focus to all of them.
276
+ if (element.getAttribute('disabled') !== null)
277
+ return 'none';
278
+ if (element.closest('[inert]') !== null)
279
+ return 'none';
280
+ // `hidden` TOO, and for the same reason: the browser takes a hidden subtree
281
+ // out of the tab order, so a native button inside one is not reachable
282
+ // however focusable its tag is. Nothing in this package renders it today —
283
+ // which is exactly why it is worth handling here rather than later, since
284
+ // `controlSurface` is exported for hosts to run over their own chrome.
285
+ if (element.closest('[hidden]') !== null)
286
+ return 'none';
287
+ const raw = element.getAttribute('tabindex');
288
+ if (raw === null) {
289
+ // NATIVELY IN THE TAB ORDER. `a` only with an `href`: without one it is not
290
+ // focusable, and recording it as a tab stop would claim a reachability the
291
+ // markup does not have.
292
+ const tag = element.tagName.toLowerCase();
293
+ if (tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea')
294
+ return 'tab';
295
+ return tag === 'a' && element.getAttribute('href') !== null ? 'tab' : 'none';
296
+ }
297
+ const index = Number(raw);
298
+ if (!Number.isInteger(index))
299
+ return 'none';
300
+ return index < 0 ? 'programmatic' : 'tab';
301
+ }
302
+ /**
303
+ * Every id under `root`, gathered once.
304
+ *
305
+ * A SET RATHER THAN A QUERY PER TOKEN, and that is a correctness fix, not a
306
+ * speed one. An earlier revision resolved each IDREF with
307
+ * `` querySelectorAll(`[id="${id}"]`) `` — interpolating a value read off the
308
+ * DOM straight into a selector, which is verbatim the class the mount's focus
309
+ * token was written to avoid. Measured: `aria-describedby='a"]'` made this
310
+ * function THROW, and a token containing `],[id` resolved against the wrong
311
+ * elements. `controlSurface` is exported for hosts to run over their own
312
+ * chrome, where ids are tracker-derived, so the injection was reachable.
313
+ *
314
+ * SCOPED TO `root`, which is a real bound and is stated rather than hidden: an
315
+ * IDREF pointing into the host's own chrome outside the mounted surface reads
316
+ * as `dangling` here. That is the right default for a record ABOUT this
317
+ * surface, and a host taking it over its whole page gets the wider answer.
318
+ */
319
+ function idsUnder(root) {
320
+ const ids = new Set();
321
+ // `root` ITSELF IS NOT IN ITS OWN `querySelectorAll`, so it is added by hand:
322
+ // a host may well hang the surface off an element that carries an id.
323
+ const own = root.getAttribute('id');
324
+ if (own !== null)
325
+ ids.add(own);
326
+ for (const element of root.querySelectorAll('[id]')) {
327
+ const id = element.getAttribute('id');
328
+ if (id !== null)
329
+ ids.add(id);
330
+ }
331
+ return ids;
332
+ }
333
+ function ariaOf(ids, element) {
334
+ const out = {};
335
+ for (const attribute of ENUMERATED_ARIA) {
336
+ const value = element.getAttribute(attribute);
337
+ if (value !== null)
338
+ out[attribute] = value;
339
+ }
340
+ // `aria-hidden` IS INHERITED, and the rule that reads it is about exactly
341
+ // that. A wrapper carrying it takes its descendants out of the accessibility
342
+ // tree WITHOUT taking them out of the tab order — which is the "focusable and
343
+ // announces nothing" case the rule exists to reject. Read off the element
344
+ // alone, the rule could not see the shape it was written for: the entry
345
+ // carried no `aria-hidden` at all and passed.
346
+ //
347
+ // The other enumerated states are properties of the element that carries
348
+ // them, so only this one is resolved through ancestry.
349
+ if (element.closest('[aria-hidden="true"]') !== null)
350
+ out['aria-hidden'] = 'true';
351
+ for (const attribute of IDREF_ARIA) {
352
+ const value = element.getAttribute(attribute);
353
+ if (value === null)
354
+ continue;
355
+ // EVERY id IT NAMES, because the attribute takes a list and a half-resolved
356
+ // reference is still broken for the token that dangles.
357
+ const named = value.split(/\s+/).filter((token) => token !== '');
358
+ out[attribute] =
359
+ named.length > 0 && named.every((id) => ids.has(id)) ? 'resolves' : 'dangling';
360
+ }
361
+ return out;
362
+ }
363
+ /**
364
+ * Every control under `root`, in document order, sorted so the record is stable.
365
+ *
366
+ * Pure and total. SORTED RATHER THAN LEFT IN DOCUMENT ORDER: a baseline is
367
+ * diffed by people, and a control moving between zones should read as one
368
+ * changed line rather than as a reordering of the whole file. Document order is
369
+ * a fact about layout, which the zone already carries.
370
+ *
371
+ * The bound it does NOT cover is stated where it can be checked: a control
372
+ * publishing itself on some fourth attribute is invisible here, and
373
+ * {@link CONTROL_ATTRIBUTES} is the list to extend.
374
+ */
375
+ export function controlSurface(root) {
376
+ const entries = [];
377
+ const seen = new Set();
378
+ const ids = idsUnder(root);
379
+ for (const channel of CONTROL_ATTRIBUTES) {
380
+ for (const element of root.querySelectorAll(`[${channel}]`)) {
381
+ const control = element.getAttribute(channel);
382
+ // ONE ENTRY PER ELEMENT, even where a control carries two channels: the
383
+ // record is about the control, and a second row for one button would
384
+ // make every rule below count it twice.
385
+ if (control === null || seen.has(element))
386
+ continue;
387
+ seen.add(element);
388
+ const tag = element.tagName.toLowerCase();
389
+ entries.push({
390
+ zone: element.closest('.ig-zone')?.getAttribute('data-zone') ?? null,
391
+ channel,
392
+ control,
393
+ target: element.getAttribute('data-ig-target'),
394
+ value: element.getAttribute('data-ig-value') ?? element.getAttribute('data-ig-kind'),
395
+ tag,
396
+ role: element.getAttribute('role') ??
397
+ IMPLICIT_ROLES[tag] ??
398
+ conditionalRole(root, element, tag),
399
+ tabStop: tabStopOf(element),
400
+ inert: element.closest('[inert]') !== null,
401
+ name: nameSource(root, element),
402
+ aria: ariaOf(ids, element),
403
+ });
404
+ }
405
+ }
406
+ // FIELD BY FIELD, BY CODE POINT. `localeCompare` was both non-total and
407
+ // machine-dependent here: it treats `\u0000` as ignorable, so the separator
408
+ // bought nothing and distinct keys compared EQUAL, and with no locale it
409
+ // follows the runner's own ICU build — which would reorder a committed
410
+ // artifact that is compared with an order-sensitive `deepEqual`.
411
+ const key = (entry) => [
412
+ entry.zone ?? '',
413
+ entry.channel,
414
+ entry.control,
415
+ entry.target ?? '',
416
+ entry.value ?? '',
417
+ ];
418
+ return [...entries].sort((a, b) => {
419
+ const left = key(a);
420
+ const right = key(b);
421
+ for (let index = 0; index < left.length; index += 1) {
422
+ const one = left[index] ?? '';
423
+ const other = right[index] ?? '';
424
+ if (one !== other)
425
+ return one < other ? -1 : 1;
426
+ }
427
+ return 0;
428
+ });
429
+ }
430
+ //# sourceMappingURL=baseline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../src/a11y/baseline.ts"],"names":[],"mappings":"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"}
@@ -33,5 +33,5 @@
33
33
  * There is no transition, no animation and no `@keyframes` here, and there is a
34
34
  * test that says so.
35
35
  */
36
- export declare const auditStylesheet = "\n.ig-audit {\n align-items: center;\n display: inline-flex;\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size-small);\n gap: var(--ig-space-tight);\n}\n\n.ig-audit-toggle {\n align-items: center;\n background: none;\n border: 0;\n color: var(--ig-text-muted);\n cursor: pointer;\n display: inline-flex;\n font: inherit;\n gap: var(--ig-space-tight);\n padding: 0;\n}\n\n.ig-audit-toggle[aria-pressed='true'] {\n color: var(--ig-text);\n}\n\n.ig-audit-count {\n color: var(--ig-text);\n font-family: var(--ig-font-mono);\n font-variant-numeric: tabular-nums;\n}\n\n[data-ig-audit] {\n box-shadow: inset var(--ig-stroke) 0 0 0 var(--ig-edge-serialize-with);\n}\n";
36
+ export declare const auditStylesheet = "\n.ig-audit {\n align-items: center;\n display: inline-flex;\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size-small);\n gap: var(--ig-space-tight);\n}\n\n.ig-audit-toggle {\n align-items: center;\n background: none;\n border: 0;\n color: var(--ig-text-muted);\n cursor: pointer;\n display: inline-flex;\n font: inherit;\n gap: var(--ig-space-tight);\n padding: 0;\n}\n\n.ig-audit-toggle[aria-pressed='true'] {\n color: var(--ig-text);\n}\n\n.ig-audit-count {\n color: var(--ig-text);\n font-family: var(--ig-font-mono);\n font-variant-numeric: tabular-nums;\n}\n\n[data-ig-audit] {\n box-shadow: inset var(--ig-stroke-audit) 0 0 0 var(--ig-edge-serialize-with);\n}\n";
37
37
  //# sourceMappingURL=styles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/audit/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAIH,eAAO,MAAM,eAAe,6rBAkC3B,CAAC"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/audit/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAIH,eAAO,MAAM,eAAe,msBAkC3B,CAAC"}
@@ -66,7 +66,7 @@ export const auditStylesheet = `
66
66
  }
67
67
 
68
68
  [${AUDIT_SEVERITY_ATTRIBUTE}] {
69
- box-shadow: inset var(--ig-stroke) 0 0 0 var(--ig-edge-serialize-with);
69
+ box-shadow: inset var(--ig-stroke-audit) 0 0 0 var(--ig-edge-serialize-with);
70
70
  }
71
71
  `;
72
72
  //# sourceMappingURL=styles.js.map
@@ -65,6 +65,23 @@ export interface CreateDraft {
65
65
  }
66
66
  /** Nothing gathered. The state before a create starts and after one emits. */
67
67
  export declare const IDLE_CREATE_DRAFT: CreateDraft;
68
+ /**
69
+ * Whether the draft is at the KIND step: a source gathered, no kind yet.
70
+ *
71
+ * A PREDICATE RATHER THAN A SHELL'S TWO NULL CHECKS, because two of them
72
+ * disagreed. `render.ts`'s panel asks this question to draw the kind list and
73
+ * `mount.ts` now asks it to classify the keyboard, and a step whose definition
74
+ * is written out at each site is one a later edit can move at one of them —
75
+ * which is how the chooser came to be drawn at a moment the key map did not
76
+ * recognise (`#152`).
77
+ *
78
+ * IT ASKS ABOUT THE DRAFT ALONE, and deliberately says nothing about focus or
79
+ * about which of the two choosers is on screen. Whether a drop is live decides
80
+ * WHICH renderer draws the step, never WHETHER the reader is at it; folding that
81
+ * in would give this predicate a second subject and make it false for the
82
+ * floating chooser, which is the one opened by a pointer.
83
+ */
84
+ export declare function isChoosingKind(draft: CreateDraft): boolean;
68
85
  /**
69
86
  * One fact arriving, from whichever path gathered it.
70
87
  *
@@ -1 +1 @@
1
- {"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/create/draft.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC,wCAAwC;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;CAChC;AAED,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,WAI9B,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEhC;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CACpC;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,YAAY,CAmCtF"}
1
+ {"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/create/draft.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC,wCAAwC;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;CAChC;AAED,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,WAI9B,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAE1D;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEhC;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CACpC;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,YAAY,CAmCtF"}
@@ -53,6 +53,25 @@ export const IDLE_CREATE_DRAFT = Object.freeze({
53
53
  target: null,
54
54
  kind: null,
55
55
  });
56
+ /**
57
+ * Whether the draft is at the KIND step: a source gathered, no kind yet.
58
+ *
59
+ * A PREDICATE RATHER THAN A SHELL'S TWO NULL CHECKS, because two of them
60
+ * disagreed. `render.ts`'s panel asks this question to draw the kind list and
61
+ * `mount.ts` now asks it to classify the keyboard, and a step whose definition
62
+ * is written out at each site is one a later edit can move at one of them —
63
+ * which is how the chooser came to be drawn at a moment the key map did not
64
+ * recognise (`#152`).
65
+ *
66
+ * IT ASKS ABOUT THE DRAFT ALONE, and deliberately says nothing about focus or
67
+ * about which of the two choosers is on screen. Whether a drop is live decides
68
+ * WHICH renderer draws the step, never WHETHER the reader is at it; folding that
69
+ * in would give this predicate a second subject and make it false for the
70
+ * floating chooser, which is the one opened by a pointer.
71
+ */
72
+ export function isChoosingKind(draft) {
73
+ return draft.source !== null && draft.kind === null;
74
+ }
56
75
  function complete(draft) {
57
76
  const { source, target, kind } = draft;
58
77
  if (source === null || target === null || kind === null)
@@ -1 +1 @@
1
- {"version":3,"file":"draft.js","sourceRoot":"","sources":["../../src/create/draft.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAoBH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,iBAAiB,GAAgB,MAAM,CAAC,MAAM,CAAC;IAC1D,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;CACX,CAAC,CAAC;AA2CH,SAAS,QAAQ,CAAC,KAAkB;IAClC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvC,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACrE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAAC,KAAkB,EAAE,OAAsB;IACtE,MAAM,IAAI,GAAG,CAAC,GAAgB,EAAE;QAC9B,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,OAAO;gBACV,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAC9D,KAAK,QAAQ;gBACX,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;YAC3C,KAAK,MAAM;gBACT,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC9C,KAAK,QAAQ;gBACX,OAAO,iBAAiB,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,wEAAwE;IACxE,4EAA4E;IAC5E,6EAA6E;IAC7E,uEAAuE;IACvE,6EAA6E;IAC7E,yEAAyE;IACzE,EAAE;IACF,2EAA2E;IAC3E,6EAA6E;IAC7E,oEAAoE;IACpE,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAE3D,4EAA4E;IAC5E,2EAA2E;IAC3E,2EAA2E;IAC3E,sEAAsE;IACtE,OAAO;QACL,KAAK,EAAE,iBAAiB;QACxB,QAAQ,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE;KACnF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"draft.js","sourceRoot":"","sources":["../../src/create/draft.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAoBH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,iBAAiB,GAAgB,MAAM,CAAC,MAAM,CAAC;IAC1D,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;CACX,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,OAAO,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;AACtD,CAAC;AA2CD,SAAS,QAAQ,CAAC,KAAkB;IAClC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvC,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACrE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAAC,KAAkB,EAAE,OAAsB;IACtE,MAAM,IAAI,GAAG,CAAC,GAAgB,EAAE;QAC9B,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,OAAO;gBACV,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAC9D,KAAK,QAAQ;gBACX,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;YAC3C,KAAK,MAAM;gBACT,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC9C,KAAK,QAAQ;gBACX,OAAO,iBAAiB,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,wEAAwE;IACxE,4EAA4E;IAC5E,6EAA6E;IAC7E,uEAAuE;IACvE,6EAA6E;IAC7E,yEAAyE;IACzE,EAAE;IACF,2EAA2E;IAC3E,6EAA6E;IAC7E,oEAAoE;IACpE,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAE3D,4EAA4E;IAC5E,2EAA2E;IAC3E,2EAA2E;IAC3E,sEAAsE;IACtE,OAAO;QACL,KAAK,EAAE,iBAAiB;QACxB,QAAQ,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE;KACnF,CAAC;AACJ,CAAC"}