@orkestrel/test 0.0.18 → 0.0.19

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.
@@ -1,6 +1,6 @@
1
1
  import { isError, isString } from "@orkestrel/contract";
2
- import { STATECHART_ATTRIBUTES, STATECHART_STATUSES, buildRefusal, checkBounds, executeScenario, requireValue, waitForAbort, waitForCondition, waitForDelay } from "../core/index.js";
3
- import { commands, page, userEvent } from "vitest/browser";
2
+ import { STATECHART_ATTRIBUTES, STATECHART_STATUSES, buildRefusal, checkBounds, executeScenario, invokeUnchecked, readProperty, requireValue, waitForAbort, waitForCondition, waitForDelay } from "../core/index.js";
3
+ import { cdp, commands, page, userEvent } from "vitest/browser";
4
4
  //#region src/browser/constants.ts
5
5
  /**
6
6
  * Names the interactive ARIA roles a bare accessible name is searched across.
@@ -192,6 +192,22 @@ var IMPLICIT_ROLES = Object.freeze({
192
192
  TR: "row",
193
193
  UL: "list"
194
194
  });
195
+ /**
196
+ * Names the tester root's attribute holding the media readings observed before the first stage.
197
+ *
198
+ * @remarks
199
+ * The value is a bit string in print, reduced motion, dark colour scheme, and forced colours order.
200
+ * Each bit is `1` for a matching query and `0` otherwise, for example `0100`.
201
+ */
202
+ var MEDIA_STAGE = "data-media-stage";
203
+ /**
204
+ * Names the tester root's attribute holding the pressed pointer's page coordinates.
205
+ *
206
+ * @remarks
207
+ * The value has the form `<x>x<y>`. The release removes it only after the button-up send resolves,
208
+ * so a rejected send keeps the marker for a retry.
209
+ */
210
+ var POINTER_HOLD = "data-pointer-hold";
195
211
  //#endregion
196
212
  //#region src/browser/helpers.ts
197
213
  /**
@@ -529,6 +545,119 @@ async function clickDisclosure(name) {
529
545
  await userEvent.click(target);
530
546
  }
531
547
  /**
548
+ * Sends one DevTools protocol command through the browser provider.
549
+ *
550
+ * @param method - The protocol method name.
551
+ * @param params - The protocol parameters.
552
+ * @returns A promise resolving after the command completes, discarding its response.
553
+ * @throws Thrown when the provider exposes no DevTools session, or the command fails.
554
+ *
555
+ * @example
556
+ * ```ts
557
+ * await sendProtocol('Emulation.setEmulatedMedia', { media: '', features: [] })
558
+ * ```
559
+ */
560
+ async function sendProtocol(method, params) {
561
+ let session;
562
+ let send;
563
+ try {
564
+ session = cdp();
565
+ send = readProperty(session, "send");
566
+ } catch (cause) {
567
+ throw new Error("Browser provider exposes no DevTools session", { cause });
568
+ }
569
+ if (typeof send !== "function") throw new Error("Browser provider exposes no DevTools session");
570
+ await invokeUnchecked(session, send, [method, params]);
571
+ }
572
+ async function hoverAccessible(first, second) {
573
+ await userEvent.hover(resolveRendered(first, second));
574
+ }
575
+ async function holdAccessible(first, second) {
576
+ const held = document.documentElement.getAttribute(POINTER_HOLD);
577
+ if (held !== null) throw new Error(`Pointer is already held at ${held}`);
578
+ const target = second === void 0 ? resolveAccessible(first) : resolveAccessible(first, second);
579
+ const box = target.getBoundingClientRect();
580
+ const frame = window.frameElement?.getBoundingClientRect();
581
+ const scale = frame === void 0 ? 1 : frame.width / window.innerWidth;
582
+ const x = (frame?.left ?? 0) + (box.left + box.width / 2) * scale;
583
+ const y = (frame?.top ?? 0) + (box.top + box.height / 2) * scale;
584
+ await sendProtocol("Input.dispatchMouseEvent", {
585
+ type: "mouseMoved",
586
+ x,
587
+ y
588
+ });
589
+ await sendProtocol("Input.dispatchMouseEvent", {
590
+ type: "mousePressed",
591
+ x,
592
+ y,
593
+ button: "left",
594
+ buttons: 1,
595
+ clickCount: 1
596
+ });
597
+ document.documentElement.setAttribute(POINTER_HOLD, `${String(x)}x${String(y)}`);
598
+ await waitForFrame();
599
+ if (!target.matches(":active")) {
600
+ try {
601
+ await releasePointer();
602
+ } catch (cause) {
603
+ throw new Error(`Interactive target "${second ?? first}" did not enter the pressed state`, { cause });
604
+ }
605
+ throw new Error(`Interactive target "${second ?? first}" did not enter the pressed state`);
606
+ }
607
+ }
608
+ /**
609
+ * Releases a held pointer and parks it at the page origin, clearing hover.
610
+ *
611
+ * @returns A promise resolving after the released pointer's frame paints.
612
+ * @throws Thrown when the release or the park rejects. If both reject, the aggregate carries the
613
+ * park rejection as its cause and the release rejection in its errors.
614
+ *
615
+ * @remarks
616
+ * An idle pointer sends no button release. Calling this after an explicit release is safe in an
617
+ * `afterEach` hook. A rejected release keeps the marker for a later retry. The pointer still moves
618
+ * to the origin in cleanup, and a rejection there joins the aggregate described under `@throws`.
619
+ * The provider must expose a DevTools session.
620
+ *
621
+ * @example
622
+ * ```ts
623
+ * await releasePointer()
624
+ * ```
625
+ */
626
+ async function releasePointer() {
627
+ const held = document.documentElement.getAttribute(POINTER_HOLD);
628
+ let released = held === null;
629
+ let rejection;
630
+ try {
631
+ if (held !== null) {
632
+ const [x, y] = held.split("x").map(Number);
633
+ await sendProtocol("Input.dispatchMouseEvent", {
634
+ type: "mouseReleased",
635
+ x,
636
+ y,
637
+ button: "left",
638
+ buttons: 0,
639
+ clickCount: 1
640
+ });
641
+ released = true;
642
+ }
643
+ } catch (cause) {
644
+ rejection = cause;
645
+ }
646
+ if (released) document.documentElement.removeAttribute(POINTER_HOLD);
647
+ try {
648
+ await sendProtocol("Input.dispatchMouseEvent", {
649
+ type: "mouseMoved",
650
+ x: 0,
651
+ y: 0
652
+ });
653
+ await waitForFrame();
654
+ } catch (cause) {
655
+ if (!released) throw new AggregateError([rejection], isError(cause) ? cause.message : String(cause), { cause });
656
+ throw cause;
657
+ }
658
+ if (!released) throw rejection;
659
+ }
660
+ /**
532
661
  * Replaces a named field's value through focus, select-all, deletion, and real keystrokes.
533
662
  *
534
663
  * @param name - The field's exact accessible name.
@@ -1271,53 +1400,317 @@ function removeDatabase(name) {
1271
1400
  });
1272
1401
  }
1273
1402
  /**
1274
- * Parses one computed CSS color value into straight sRGB channels.
1403
+ * Converts normalized encoded sRGB channels to the clipped paint scale.
1404
+ *
1405
+ * @param red - The encoded red channel, with `1` representing full intensity.
1406
+ * @param green - The encoded green channel.
1407
+ * @param blue - The encoded blue channel.
1408
+ * @param alpha - The opacity. Default: `1`.
1409
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1410
+ *
1411
+ * @example
1412
+ * ```ts
1413
+ * convertSRGB(1.2, -0.1, 0.5) // [255, 0, 127.5, 1]
1414
+ * ```
1415
+ */
1416
+ function convertSRGB(red, green, blue, alpha = 1) {
1417
+ return Object.freeze([
1418
+ Math.min(255, Math.max(0, red * 255)),
1419
+ Math.min(255, Math.max(0, green * 255)),
1420
+ Math.min(255, Math.max(0, blue * 255)),
1421
+ Math.min(1, Math.max(0, alpha))
1422
+ ]);
1423
+ }
1424
+ /**
1425
+ * Converts linear sRGB channels to encoded, clipped paint channels.
1275
1426
  *
1276
- * @param value - A computed `rgb()`, `rgba()`, or `color(srgb …)` value.
1277
- * @returns The color's channels, or `undefined` when the value names no color this reader speaks.
1427
+ * @param red - The linear red channel on the normalized scale.
1428
+ * @param green - The linear green channel.
1429
+ * @param blue - The linear blue channel.
1430
+ * @param alpha - The opacity. Default: `1`.
1431
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1278
1432
  *
1279
1433
  * @remarks
1280
- * A computed color resolves to `rgb()` or `rgba()` for every legacy source, and a `color-mix()`
1281
- * declaration resolves to `color(srgb r g b [/ a])` with channels on the 0–1 scale. Both forms are
1282
- * read here and nothing else is: a keyword, a hex triple, an empty string from a detached element,
1283
- * and a color space the cascade never hands back all return `undefined`. Absence is the answer
1284
- * rather than a transparent color, so a caller decides what an unreadable value means instead of
1285
- * measuring a black it never saw.
1434
+ * Applies the CSS Color 4 extended sRGB transfer function before clipping.
1286
1435
  *
1287
1436
  * @example
1288
1437
  * ```ts
1289
- * parseColor('rgba(255, 255, 255, 0.5)') // [255, 255, 255, 0.5]
1290
- * parseColor('rebeccapurple') // undefined
1438
+ * convertLinearSRGB(0, 0, 0) // [0, 0, 0, 1]
1291
1439
  * ```
1292
1440
  */
1293
- function parseColor(value) {
1294
- const modern = /^color\(srgb\s+(?<red>[\d.]+)\s+(?<green>[\d.]+)\s+(?<blue>[\d.]+)(?:\s*\/\s*(?<alpha>[\d.]+))?\)$/u.exec(value);
1295
- const legacy = /^rgba?\((?<channels>[^)]*)\)$/u.exec(value);
1296
- const [red, green, blue, alpha = 1] = modern?.groups === void 0 ? (legacy?.groups?.channels ?? "").split(/[\s,/]+/u).filter((part) => part.length > 0).map((part) => Number.parseFloat(part)) : [
1297
- Number.parseFloat(modern.groups.red ?? "") * 255,
1298
- Number.parseFloat(modern.groups.green ?? "") * 255,
1299
- Number.parseFloat(modern.groups.blue ?? "") * 255,
1300
- modern.groups.alpha === void 0 ? 1 : Number.parseFloat(modern.groups.alpha)
1301
- ];
1302
- if (red === void 0 || green === void 0 || blue === void 0) return void 0;
1303
- if (![
1441
+ function convertLinearSRGB(red, green, blue, alpha = 1) {
1442
+ const [encodedRed = 0, encodedGreen = 0, encodedBlue = 0] = [
1304
1443
  red,
1305
1444
  green,
1306
- blue,
1307
- alpha
1308
- ].every((channel) => Number.isFinite(channel))) return void 0;
1309
- return Object.freeze([
1445
+ blue
1446
+ ].map((channel) => Math.abs(channel) <= .0031308 ? 12.92 * channel : Math.sign(channel) * (1.055 * Math.abs(channel) ** (1 / 2.4) - .055));
1447
+ return convertSRGB(encodedRed, encodedGreen, encodedBlue, alpha);
1448
+ }
1449
+ /**
1450
+ * Converts D65 XYZ coordinates to clipped sRGB paint channels.
1451
+ *
1452
+ * @param x - The normalized X coordinate.
1453
+ * @param y - The normalized Y coordinate.
1454
+ * @param z - The normalized Z coordinate.
1455
+ * @param alpha - The opacity. Default: `1`.
1456
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1457
+ *
1458
+ * @remarks
1459
+ * Uses the CSS Color 4 XYZ D65 to linear sRGB matrix, then the sRGB transfer function.
1460
+ *
1461
+ * @example
1462
+ * ```ts
1463
+ * convertXYZD65(0, 0, 0) // [0, 0, 0, 1]
1464
+ * ```
1465
+ */
1466
+ function convertXYZD65(x, y, z, alpha = 1) {
1467
+ return convertLinearSRGB(12831 / 3959 * x - 329 / 214 * y - 1974 / 3959 * z, -851781 / 878810 * x + 1648619 / 878810 * y + 36519 / 878810 * z, 705 / 12673 * x - 2585 / 12673 * y + 705 / 667 * z, alpha);
1468
+ }
1469
+ /**
1470
+ * Converts D50 XYZ coordinates to clipped sRGB paint channels.
1471
+ *
1472
+ * @param x - The normalized X coordinate relative to D50.
1473
+ * @param y - The normalized Y coordinate relative to D50.
1474
+ * @param z - The normalized Z coordinate relative to D50.
1475
+ * @param alpha - The opacity. Default: `1`.
1476
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1477
+ *
1478
+ * @remarks
1479
+ * Applies the CSS Color 4 Bradford adaptation from D50 to D65 before converting to sRGB.
1480
+ *
1481
+ * @example
1482
+ * ```ts
1483
+ * convertXYZD50(0, 0, 0) // [0, 0, 0, 1]
1484
+ * ```
1485
+ */
1486
+ function convertXYZD50(x, y, z, alpha = 1) {
1487
+ return convertXYZD65(.955473421488075 * x - .02309845494876471 * y + .06325924320057072 * z, -.0283697093338637 * x + 1.0099953980813041 * y + .021041441191917323 * z, .012314014864481998 * x - .020507649298898964 * y + 1.330365926242124 * z, alpha);
1488
+ }
1489
+ /**
1490
+ * Converts OKLab coordinates to clipped sRGB paint channels.
1491
+ *
1492
+ * @param lightness - The OKLab lightness on the 0–1 scale.
1493
+ * @param a - The signed green-to-red axis.
1494
+ * @param b - The signed blue-to-yellow axis.
1495
+ * @param alpha - The opacity. Default: `1`.
1496
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1497
+ *
1498
+ * @remarks
1499
+ * Cubes the transformed cone responses before applying the linear sRGB matrix.
1500
+ *
1501
+ * @example
1502
+ * ```ts
1503
+ * convertOKLab(0, 0, 0) // [0, 0, 0, 1]
1504
+ * ```
1505
+ */
1506
+ function convertOKLab(lightness, a, b, alpha = 1) {
1507
+ const long = (lightness + .3963377773761749 * a + .2158037573099136 * b) ** 3;
1508
+ const medium = (lightness - .1055613458156586 * a - .0638541728258133 * b) ** 3;
1509
+ const short = (lightness - .0894841775298119 * a - 1.2914855480194092 * b) ** 3;
1510
+ return convertLinearSRGB(4.076741661347994 * long - 3.307711590408193 * medium + .230969929060199 * short, -1.2684380040921763 * long + 2.6097574006633715 * medium - .3413193965711952 * short, -.0041960865418371 * long - .7034186144594493 * medium + 1.7076147010012863 * short, alpha);
1511
+ }
1512
+ /**
1513
+ * Converts CIE Lab coordinates relative to D50 to clipped sRGB paint channels.
1514
+ *
1515
+ * @param lightness - The CIE lightness on the 0–100 scale.
1516
+ * @param a - The signed green-to-red axis.
1517
+ * @param b - The signed blue-to-yellow axis.
1518
+ * @param alpha - The opacity. Default: `1`.
1519
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1520
+ *
1521
+ * @remarks
1522
+ * Resolves the CSS Color 4 Lab curve against the D50 white point before adapting to D65.
1523
+ *
1524
+ * @example
1525
+ * ```ts
1526
+ * convertLab(0, 0, 0) // [0, 0, 0, 1]
1527
+ * ```
1528
+ */
1529
+ function convertLab(lightness, a, b, alpha = 1) {
1530
+ const luminance = (lightness + 16) / 116;
1531
+ const [x = 0, y = 0, z = 0] = [
1532
+ luminance + a / 500,
1533
+ luminance,
1534
+ luminance - b / 200
1535
+ ].map((channel) => channel ** 3 > 216 / 24389 ? channel ** 3 : (116 * channel - 16) / (24389 / 27));
1536
+ return convertXYZD50(x * (.3457 / .3585), y, z * (.2958 / .3585), alpha);
1537
+ }
1538
+ /**
1539
+ * Converts encoded Display P3 channels to clipped sRGB paint channels.
1540
+ *
1541
+ * @param red - The normalized encoded red channel.
1542
+ * @param green - The normalized encoded green channel.
1543
+ * @param blue - The normalized encoded blue channel.
1544
+ * @param alpha - The opacity. Default: `1`.
1545
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1546
+ *
1547
+ * @remarks
1548
+ * Decodes the extended sRGB transfer curve and uses the CSS Color 4 P3 to XYZ D65 matrix.
1549
+ *
1550
+ * @example
1551
+ * ```ts
1552
+ * convertDisplayP3(0, 0, 0) // [0, 0, 0, 1]
1553
+ * ```
1554
+ */
1555
+ function convertDisplayP3(red, green, blue, alpha = 1) {
1556
+ const [r = 0, g = 0, b = 0] = [
1310
1557
  red,
1311
1558
  green,
1312
- blue,
1313
- alpha
1314
- ]);
1559
+ blue
1560
+ ].map((channel) => Math.abs(channel) <= .04045 ? channel / 12.92 : Math.sign(channel) * ((Math.abs(channel) + .055) / 1.055) ** 2.4);
1561
+ return convertXYZD65(608311 / 1250200 * r + 189793 / 714400 * g + 198249 / 1000160 * b, 35783 / 156275 * r + 247089 / 357200 * g + 198249 / 2500400 * b, 32229 / 714400 * g + 5220557 / 5000800 * b, alpha);
1562
+ }
1563
+ /**
1564
+ * Converts encoded A98 RGB channels to clipped sRGB paint channels.
1565
+ *
1566
+ * @param red - The normalized encoded red channel.
1567
+ * @param green - The normalized encoded green channel.
1568
+ * @param blue - The normalized encoded blue channel.
1569
+ * @param alpha - The opacity. Default: `1`.
1570
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1571
+ *
1572
+ * @remarks
1573
+ * Decodes the signed 563/256 power curve and uses the CSS Color 4 A98 RGB to XYZ D65 matrix.
1574
+ *
1575
+ * @example
1576
+ * ```ts
1577
+ * convertA98RGB(0, 0, 0) // [0, 0, 0, 1]
1578
+ * ```
1579
+ */
1580
+ function convertA98RGB(red, green, blue, alpha = 1) {
1581
+ const [r = 0, g = 0, b = 0] = [
1582
+ red,
1583
+ green,
1584
+ blue
1585
+ ].map((channel) => Math.sign(channel) * Math.abs(channel) ** (563 / 256));
1586
+ return convertXYZD65(573536 / 994567 * r + 263643 / 1420810 * g + 187206 / 994567 * b, 591459 / 1989134 * r + 6239551 / 9945670 * g + 374412 / 4972835 * b, 53769 / 1989134 * r + 351524 / 4972835 * g + 4929758 / 4972835 * b, alpha);
1587
+ }
1588
+ /**
1589
+ * Converts encoded ProPhoto RGB channels to clipped sRGB paint channels.
1590
+ *
1591
+ * @param red - The normalized encoded red channel.
1592
+ * @param green - The normalized encoded green channel.
1593
+ * @param blue - The normalized encoded blue channel.
1594
+ * @param alpha - The opacity. Default: `1`.
1595
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1596
+ *
1597
+ * @remarks
1598
+ * Decodes the signed ProPhoto curve, converts to XYZ D50, and adapts to D65 before clipping.
1599
+ *
1600
+ * @example
1601
+ * ```ts
1602
+ * convertProPhotoRGB(0, 0, 0) // [0, 0, 0, 1]
1603
+ * ```
1604
+ */
1605
+ function convertProPhotoRGB(red, green, blue, alpha = 1) {
1606
+ const [r = 0, g = 0, b = 0] = [
1607
+ red,
1608
+ green,
1609
+ blue
1610
+ ].map((channel) => Math.abs(channel) <= 16 / 512 ? channel / 16 : Math.sign(channel) * Math.abs(channel) ** 1.8);
1611
+ return convertXYZD50(.7977666449006423 * r + .13518129740053308 * g + .0313477341283922 * b, .2880748288194013 * r + .711835234241873 * g + 8993693872564e-17 * b, .8251046025104602 * b, alpha);
1612
+ }
1613
+ /**
1614
+ * Converts encoded Rec. 2020 channels to clipped sRGB paint channels.
1615
+ *
1616
+ * @param red - The normalized encoded red channel.
1617
+ * @param green - The normalized encoded green channel.
1618
+ * @param blue - The normalized encoded blue channel.
1619
+ * @param alpha - The opacity. Default: `1`.
1620
+ * @returns Frozen straight sRGB channels clipped to 0–255, with alpha clipped to 0–1.
1621
+ *
1622
+ * @remarks
1623
+ * Uses the piecewise Rec. 2020 transfer curve Chromium computes and the CSS Color 4 XYZ matrix.
1624
+ *
1625
+ * @example
1626
+ * ```ts
1627
+ * convertRec2020(0, 0, 0) // [0, 0, 0, 1]
1628
+ * ```
1629
+ */
1630
+ function convertRec2020(red, green, blue, alpha = 1) {
1631
+ const [r = 0, g = 0, b = 0] = [
1632
+ red,
1633
+ green,
1634
+ blue
1635
+ ].map((channel) => Math.abs(channel) < .08124285829863151 ? channel / 4.5 : Math.sign(channel) * ((Math.abs(channel) + 1.09929682680944 - 1) / 1.09929682680944) ** (1 / .45));
1636
+ return convertXYZD65(63426534 / 99577255 * r + 20160776 / 139408157 * g + 47086771 / 278816314 * b, 26158966 / 99577255 * r + 472592308 / 697040785 * g + 8267143 / 139408157 * b, 19567812 / 697040785 * g + 295819943 / 278816314 * b, alpha);
1637
+ }
1638
+ /**
1639
+ * Parses computed CSS Color 4 values into clipped straight sRGB channels.
1640
+ *
1641
+ * @param value - A computed `rgb()`, `rgba()`, `oklab()`, `oklch()`, `lab()`, `lch()`, or `color()` value.
1642
+ * @returns Frozen channels, or `undefined` for an unsupported syntax or non-finite channel.
1643
+ *
1644
+ * @remarks
1645
+ * Reads signed channels, scientific notation, percentage lightness, degree hues, and `none` as
1646
+ * zero. The `color()` spaces are `srgb`, `srgb-linear`, `display-p3`, `a98-rgb`, `prophoto-rgb`,
1647
+ * `rec2020`, `xyz`, `xyz-d50`, and `xyz-d65`. Conversion uses the CSS Color 4 matrices and white
1648
+ * point adaptation, then clips each encoded sRGB channel to 0–255 rather than gamut-mapping it.
1649
+ * Alpha is clipped to 0–1. Keywords, hex colors, unresolved expressions, and non-finite calculations
1650
+ * such as `color(srgb calc(infinity) 0 0)` remain unreadable; use {@link parseCSSColor} to resolve
1651
+ * ordinary authored expressions through the cascade.
1652
+ *
1653
+ * @example
1654
+ * ```ts
1655
+ * parseColor('rgba(255, 255, 255, 0.5)') // [255, 255, 255, 0.5]
1656
+ * parseColor('rebeccapurple') // undefined
1657
+ * ```
1658
+ */
1659
+ function parseColor(value) {
1660
+ const match = /^(?<syntax>rgba?|oklab|oklch|lab|lch|color)\((?<body>[^()]*)\)$/u.exec(value);
1661
+ if (match?.groups === void 0) return void 0;
1662
+ const { syntax, body = "" } = match.groups;
1663
+ const legacy = syntax === "rgb" || syntax === "rgba";
1664
+ const polar = syntax === "oklch" || syntax === "lch";
1665
+ const perceptual = syntax === "oklab" || syntax === "oklch" || syntax === "lab" || syntax === "lch";
1666
+ const tokens = body.trim().split(legacy && body.includes(",") ? /\s*,\s*/u : /\s*\/\s*|\s+/u);
1667
+ const space = syntax === "color" ? tokens.shift() : syntax;
1668
+ if (tokens.length !== 3 && tokens.length !== 4) return void 0;
1669
+ if (!legacy && body.includes(",")) return void 0;
1670
+ if (body.split("/").length > 2) return void 0;
1671
+ if (body.includes("/") && (tokens.length !== 4 || !/\/\s*[^\s/]+\s*$/u.test(body))) return void 0;
1672
+ if (!(legacy && body.includes(",")) && tokens.length === 4 && !body.includes("/")) return void 0;
1673
+ const parts = tokens.map((token, index) => {
1674
+ if (token === "none") return 0;
1675
+ const part = /^(?<number>[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)(?<unit>%|deg)?$/u.exec(token);
1676
+ if (part?.groups === void 0) return NaN;
1677
+ const number = Number(part.groups.number);
1678
+ const unit = part.groups.unit;
1679
+ if (unit === "deg") return polar && index === 2 ? number : NaN;
1680
+ if (unit !== "%") return number;
1681
+ if (index === 3 || syntax === "color") return number / 100;
1682
+ if (legacy) return number * 255 / 100;
1683
+ if (index === 0) return syntax === "oklab" || syntax === "oklch" ? number / 100 : number;
1684
+ return NaN;
1685
+ });
1686
+ const [first, second, third, alpha = 1] = parts;
1687
+ if (first === void 0 || second === void 0 || third === void 0) return void 0;
1688
+ if (!parts.every((part) => Number.isFinite(part))) return void 0;
1689
+ if (legacy) return convertSRGB(first / 255, second / 255, third / 255, alpha);
1690
+ if (perceptual) {
1691
+ const lightness = Math.max(0, Math.min(syntax === "oklab" || syntax === "oklch" ? 1 : 100, first));
1692
+ const a = polar ? Math.max(0, second) * Math.cos(third * Math.PI / 180) : second;
1693
+ const b = polar ? Math.max(0, second) * Math.sin(third * Math.PI / 180) : third;
1694
+ return syntax === "oklab" || syntax === "oklch" ? convertOKLab(lightness, a, b, alpha) : convertLab(lightness, a, b, alpha);
1695
+ }
1696
+ switch (space) {
1697
+ case "srgb": return convertSRGB(first, second, third, alpha);
1698
+ case "srgb-linear": return convertLinearSRGB(first, second, third, alpha);
1699
+ case "display-p3": return convertDisplayP3(first, second, third, alpha);
1700
+ case "a98-rgb": return convertA98RGB(first, second, third, alpha);
1701
+ case "prophoto-rgb": return convertProPhotoRGB(first, second, third, alpha);
1702
+ case "rec2020": return convertRec2020(first, second, third, alpha);
1703
+ case "xyz":
1704
+ case "xyz-d65": return convertXYZD65(first, second, third, alpha);
1705
+ case "xyz-d50": return convertXYZD50(first, second, third, alpha);
1706
+ default: return;
1707
+ }
1315
1708
  }
1316
1709
  /**
1317
1710
  * Resolves any CSS color expression to straight sRGB channels, by asking the browser.
1318
1711
  *
1319
1712
  * @param value - Any value the `color` property accepts: a keyword, a hex triple, a `var()`
1320
- * reference, a `color-mix()`, or an already-computed `rgb()`.
1713
+ * reference, a `color-mix()`, or a computed CSS Color 4 value.
1321
1714
  * @returns The resolved color's channels, or `undefined` when the CSSOM refuses the value or the
1322
1715
  * computed result names no color {@link parseColor} speaks.
1323
1716
  *
@@ -1327,6 +1720,8 @@ function parseColor(value) {
1327
1720
  * cascade, and reads back what the engine computed — which is the only way a keyword, a hex triple,
1328
1721
  * or a `var()` reference becomes channels at all. The read itself goes through `parseColor`, so both
1329
1722
  * halves agree on what a computed value means.
1723
+ * Modern perceptual and predefined RGB/XYZ spaces resolve through that parser's conversions;
1724
+ * out-of-gamut sRGB channels are clipped to 0–255 after conversion.
1330
1725
  *
1331
1726
  * The probe is mounted, because an unmounted element inherits nothing and a `var()` reference to a
1332
1727
  * token declared on `:root` would resolve to the initial value instead. It is removed in a `finally`,
@@ -1454,16 +1849,23 @@ function measureContrast(front, back) {
1454
1849
  return (bright + .05) / (dark + .05);
1455
1850
  }
1456
1851
  /**
1457
- * Collects the painted layers standing between one element and the surface it sits on.
1852
+ * Collects readable background color layers and refuses an unreadable painted layer.
1458
1853
  *
1459
1854
  * @param element - The element to walk up from.
1460
1855
  * @returns Every layer the walk paints, the element's own first and the deepest last.
1856
+ * @throws Thrown when a painted background color is unreadable; the error names the element and
1857
+ * its computed value.
1461
1858
  *
1462
1859
  * @remarks
1463
1860
  * A surface token paints one ancestor while every element between it and the text paints nothing,
1464
1861
  * so a backdrop is found by walking up rather than by reading the element's own `background-color`,
1465
1862
  * which is almost always transparent. A fully transparent layer paints nothing and is left out, and
1466
1863
  * the walk stops at the first fully opaque layer, because nothing above that layer is visible.
1864
+ * Legacy and modern CSS Color 4 values resolve through {@link parseColor}, with sRGB channels
1865
+ * clipped after conversion. Non-finite calculations such as `color(srgb calc(infinity) 0 0)` are
1866
+ * deliberately unreadable. An unreadable value with an explicit zero alpha paints nothing and is
1867
+ * skipped. An empty detached-element reading paints nothing too. Background images remain outside
1868
+ * this color reader.
1467
1869
  *
1468
1870
  * The stack is what tells a resolved backdrop from an assumed one: the walk reached an opaque
1469
1871
  * surface exactly when its last layer's alpha is `1`. {@link readContrast} refuses on that reading,
@@ -1479,8 +1881,14 @@ function measureContrast(front, back) {
1479
1881
  function readLayers(element) {
1480
1882
  const layers = [];
1481
1883
  for (let node = element; node !== null; node = node.parentElement) {
1482
- const layer = parseColor(getComputedStyle(node).backgroundColor);
1483
- if (layer === void 0 || layer[3] === 0) continue;
1884
+ const computed = getComputedStyle(node).backgroundColor;
1885
+ if (computed === "") continue;
1886
+ const layer = parseColor(computed);
1887
+ if (layer === void 0) {
1888
+ if (/\/\s*(?:0(?:\.0*)?|none)\s*\)$/u.test(computed)) continue;
1889
+ throw new Error(`Computed background color is unreadable on ${node.localName}${node.id === "" ? "" : `#${node.id}`}: ${computed}`);
1890
+ }
1891
+ if (layer[3] === 0) continue;
1484
1892
  layers.push(layer);
1485
1893
  if (layer[3] >= 1) break;
1486
1894
  }
@@ -1492,10 +1900,13 @@ function readLayers(element) {
1492
1900
  * @param element - The element whose backdrop to resolve.
1493
1901
  * @param floor - The opaque color the walk ends on when nothing above it paints.
1494
1902
  * @returns The composited color a reader sees behind the element.
1903
+ * @throws Thrown when the backdrop contains an unreadable painted color layer.
1495
1904
  *
1496
1905
  * @remarks
1497
1906
  * The layers {@link readLayers} collects composite top-over-bottom onto the floor, so a 3% surface
1498
1907
  * tint reads as a tint over what shows through it rather than as a full-strength paint.
1908
+ * Those layers include the modern CSS Color 4 spaces, converted and clipped to sRGB by
1909
+ * {@link parseColor}; an unreadable painted layer refuses the entire reading.
1499
1910
  *
1500
1911
  * The floor is required, because this leaf never guesses what a document sits on. Pass
1501
1912
  * {@link CANVAS_COLOR} for the page a browser paints behind an unstyled document, or the color of
@@ -1521,7 +1932,8 @@ function readBackdrop(element, floor) {
1521
1932
  * would show through instead of assuming one.
1522
1933
  * @returns The relative-luminance contrast ratio.
1523
1934
  * @throws Thrown when the element exposes no computed foreground color, and — with `floor` omitted
1524
- * — when the walk from the element upwards reaches no opaque layer.
1935
+ * — when the walk from the element upwards reaches no opaque layer. An unreadable painted
1936
+ * background layer throws even when a floor is supplied.
1525
1937
  *
1526
1938
  * @remarks
1527
1939
  * A transparent or translucent background resolves through the element's ancestors: every painted
@@ -1529,6 +1941,8 @@ function readBackdrop(element, floor) {
1529
1941
  * base, so a 3% surface tint reads as a tint over what shows through it rather than as a
1530
1942
  * full-strength paint. A translucent foreground then resolves against that effective background
1531
1943
  * before luminance is measured.
1944
+ * Text and background colors can use the modern CSS Color 4 spaces {@link parseColor} reads;
1945
+ * each is converted to sRGB and clipped before composition and luminance measurement.
1532
1946
  *
1533
1947
  * With `floor` omitted, the walk from the target upwards must reach a fully opaque layer: the
1534
1948
  * measurement throws rather than assuming a white canvas wherever that canvas would still be part
@@ -1547,7 +1961,7 @@ function readBackdrop(element, floor) {
1547
1961
  * ```ts
1548
1962
  * const container = render('<p style="background: #000; color: #fff">Ready</p>')
1549
1963
  * readContrast(requireValue(container.firstElementChild)) // 21
1550
- * readContrast(requireValue(container.firstElementChild), CANVAS_COLOR) // 21, and never refuses
1964
+ * readContrast(requireValue(container.firstElementChild), CANVAS_COLOR) // 21
1551
1965
  * ```
1552
1966
  */
1553
1967
  function readContrast(element, floor) {
@@ -1566,6 +1980,7 @@ function readContrast(element, floor) {
1566
1980
  * @param worn - The element the control's focus chrome is painted onto. Default: `control`.
1567
1981
  * @returns The strongest ratio the painted focus chrome reaches, or `undefined` when the control is
1568
1982
  * not showing `:focus-visible` or the cascade paints no chrome of its own.
1983
+ * @throws Thrown when the focused control's backdrop contains an unreadable painted color layer.
1569
1984
  *
1570
1985
  * @remarks
1571
1986
  * This reads and never acts. Focus arrives through the published verbs — `traverseAccessible`,
@@ -1589,6 +2004,9 @@ function readContrast(element, floor) {
1589
2004
  * color names neither. A focus style that only changes the control's own fill reports `undefined`
1590
2005
  * too: the resting fill is gone by the time focus is on the control, and this never moves focus to
1591
2006
  * go and read it.
2007
+ * Outline and shadow colors include `oklch()`, `oklab()`, `lab()`, `lch()`, and predefined
2008
+ * `color()` spaces. Each readable color converts to clipped sRGB through {@link parseColor}, and
2009
+ * the result remains a contrast ratio rather than a ring width.
1592
2010
  *
1593
2011
  * @example
1594
2012
  * ```ts
@@ -1602,7 +2020,7 @@ function readRing(control, worn) {
1602
2020
  const declared = getComputedStyle(target);
1603
2021
  const backdrop = readBackdrop(target.parentElement ?? target, CANVAS_COLOR);
1604
2022
  const outline = declared.outlineStyle === "none" || declared.outlineStyle === "auto" || Number.parseFloat(declared.outlineWidth) === 0 ? void 0 : parseColor(declared.outlineColor);
1605
- const shadow = parseColor(/(?:rgba?|color)\([^)]*\)/u.exec(declared.boxShadow)?.[0] ?? "");
2023
+ const shadow = parseColor(/(?:rgba?|color|oklab|oklch|lab|lch)\([^)]*\)/u.exec(declared.boxShadow)?.[0] ?? "");
1606
2024
  const ratios = [];
1607
2025
  for (const painted of [outline, shadow]) {
1608
2026
  if (painted === void 0) continue;
@@ -1882,12 +2300,14 @@ function extractStyles(root) {
1882
2300
  return styled;
1883
2301
  }
1884
2302
  /**
1885
- * Reads one resolved CSS property from a real browser element.
2303
+ * Reads one resolved CSS property from a real browser element or a named pseudo-element.
1886
2304
  *
1887
2305
  * @param element - The element whose resolved style to inspect.
1888
2306
  * @param property - The CSS property name, registered or custom.
2307
+ * @param pseudo - The pseudo-element selector. Omit it to read the element itself.
1889
2308
  * @returns The browser's resolved property value, trimmed; an empty string when the element resolves
1890
2309
  * none.
2310
+ * @throws Thrown when the pseudo argument lacks the `::` prefix or the engine does not support it.
1891
2311
  *
1892
2312
  * @remarks
1893
2313
  * The value is trimmed, so what comes back is the value and never the whitespace around it. Internal
@@ -1898,8 +2318,12 @@ function extractStyles(root) {
1898
2318
  * readStyle(button, 'padding-left')
1899
2319
  * ```
1900
2320
  */
1901
- function readStyle(element, property) {
1902
- return getComputedStyle(element).getPropertyValue(property).trim();
2321
+ function readStyle(element, property, pseudo) {
2322
+ if (pseudo !== void 0) {
2323
+ if (!pseudo.startsWith("::")) throw new Error(`Pseudo-element "${pseudo}" must start with "::"`);
2324
+ if (!CSS.supports(`selector(${pseudo})`)) throw new Error(`Pseudo-element "${pseudo}" is not one this engine exposes`);
2325
+ }
2326
+ return getComputedStyle(element, pseudo).getPropertyValue(property).trim();
1903
2327
  }
1904
2328
  /**
1905
2329
  * Reads one custom property from an element's resolved style.
@@ -1953,7 +2377,9 @@ function readRootToken(name) {
1953
2377
  *
1954
2378
  * @param element - The element whose resolved style to inspect.
1955
2379
  * @param property - The CSS property name, registered or custom.
2380
+ * @param pseudo - The pseudo-element selector. Omit it to read the element itself.
1956
2381
  * @returns The leading numeric part of the resolved value, and `0` when it carries none.
2382
+ * @throws Thrown when the pseudo argument lacks the `::` prefix or the engine does not support it.
1957
2383
  *
1958
2384
  * @remarks
1959
2385
  * A resolved length is text with a unit — `'12px'` — so this reads the number in front of the unit
@@ -1971,8 +2397,8 @@ function readRootToken(name) {
1971
2397
  * readPixels(button, 'width') // 0 when the width resolves to `auto`
1972
2398
  * ```
1973
2399
  */
1974
- function readPixels(element, property) {
1975
- const measured = Number.parseFloat(readStyle(element, property));
2400
+ function readPixels(element, property, pseudo) {
2401
+ const measured = Number.parseFloat(readStyle(element, property, pseudo));
1976
2402
  return Number.isFinite(measured) ? measured : 0;
1977
2403
  }
1978
2404
  /**
@@ -2126,6 +2552,157 @@ async function releasePane() {
2126
2552
  if (Number.isFinite(width) && Number.isFinite(height)) await page.viewport(width, height);
2127
2553
  }
2128
2554
  /**
2555
+ * Stages the tester's print medium and motion preference through the browser provider.
2556
+ *
2557
+ * @param options - The media axes to override.
2558
+ * @returns A promise resolving after a bounded read-back for `print: true` and either
2559
+ * `motion` value. A `print: false` stage is sent and followed by a frame wait without a read-back.
2560
+ * @throws Thrown when no axis is supplied or a staged query does not reach the tester.
2561
+ *
2562
+ * @remarks
2563
+ * If `print` is true, uses print; if false, uses screen. If `motion` is true, uses no preference;
2564
+ * if false, uses reduced motion. The print medium, reduced motion, colour scheme, and forced colours
2565
+ * keep their effective readings when omitted. Any other emulated feature the provider configured
2566
+ * is cleared. Each staged query waits up to 1000 milliseconds, polling every 10 milliseconds.
2567
+ * A refused read-back restores the carried pre-call readings before throwing and can take two
2568
+ * budgets. A restoration failure is attached as the refusal's cause. Register
2569
+ * {@link releaseMedia} in teardown; it restores the readings observed before the first stage.
2570
+ *
2571
+ * @example
2572
+ * ```ts
2573
+ * await stageMedia({ motion: false, print: true })
2574
+ * await releaseMedia()
2575
+ * ```
2576
+ */
2577
+ async function stageMedia(options) {
2578
+ const print = options.print;
2579
+ const motion = options.motion;
2580
+ if (print === void 0 && motion === void 0) throw new Error("Media emulation was staged with nothing to emulate");
2581
+ const media = matchMedia("print").matches ? "print" : "screen";
2582
+ const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
2583
+ const dark = matchMedia("(prefers-color-scheme: dark)").matches;
2584
+ const forced = matchMedia("(forced-colors: active)").matches;
2585
+ if (!document.documentElement.hasAttribute("data-media-stage")) document.documentElement.setAttribute(MEDIA_STAGE, [
2586
+ media === "print",
2587
+ reduced,
2588
+ dark,
2589
+ forced
2590
+ ].map(Number).join(""));
2591
+ const features = [
2592
+ {
2593
+ name: "prefers-color-scheme",
2594
+ value: dark ? "dark" : "light"
2595
+ },
2596
+ {
2597
+ name: "forced-colors",
2598
+ value: forced ? "active" : "none"
2599
+ },
2600
+ {
2601
+ name: "prefers-reduced-motion",
2602
+ value: reduced ? "reduce" : "no-preference"
2603
+ }
2604
+ ];
2605
+ const queries = [];
2606
+ if (print === true) queries.push("print");
2607
+ if (motion !== void 0) queries.push(`(prefers-reduced-motion: ${motion ? "no-preference" : "reduce"})`);
2608
+ await sendProtocol("Emulation.setEmulatedMedia", {
2609
+ media: print === void 0 ? media : print ? "print" : "screen",
2610
+ features: features.map((feature) => feature.name === "prefers-reduced-motion" && motion !== void 0 ? {
2611
+ name: feature.name,
2612
+ value: motion ? "no-preference" : "reduce"
2613
+ } : feature)
2614
+ });
2615
+ await waitForFrame();
2616
+ for (const query of queries) try {
2617
+ await waitForCondition(query, () => matchMedia(query).matches);
2618
+ } catch (cause) {
2619
+ try {
2620
+ await sendProtocol("Emulation.setEmulatedMedia", {
2621
+ media,
2622
+ features
2623
+ });
2624
+ await waitForCondition("pre-call media readings restored", () => matchMedia(media).matches && features.every((feature) => matchMedia(`(${feature.name}: ${feature.value})`).matches));
2625
+ } catch (restoration) {
2626
+ throw new Error(`Media emulation did not reach the tester: ${query}`, { cause: restoration });
2627
+ }
2628
+ throw new Error(`Media emulation did not reach the tester: ${query}`, { cause });
2629
+ }
2630
+ }
2631
+ /**
2632
+ * Restores the media readings observed before the first stage as explicit emulation. With nothing
2633
+ * staged, clears every override and waits for a stable reading, not a proved engine baseline. Checks
2634
+ * the budget between polls, so a frame that never paints is not bounded by it.
2635
+ *
2636
+ * @returns A promise resolving after the media readings settle.
2637
+ * @throws Thrown when a media read-back exhausts its 1000 millisecond budget between polls.
2638
+ *
2639
+ * @remarks
2640
+ * Restores print, reduced motion, colour scheme, and forced colours from {@link MEDIA_STAGE},
2641
+ * waits per axis for the recorded value, and removes the marker after every axis agrees. With no
2642
+ * marker, sends the empty reset and compares readings taken strictly after that send. Each poll
2643
+ * waits for a frame; the interval is 10 milliseconds. The provider must expose a DevTools session.
2644
+ *
2645
+ * @example
2646
+ * ```ts
2647
+ * await releaseMedia()
2648
+ * ```
2649
+ */
2650
+ async function releaseMedia() {
2651
+ const queries = [
2652
+ "print",
2653
+ "(prefers-reduced-motion: reduce)",
2654
+ "(prefers-color-scheme: dark)",
2655
+ "(forced-colors: active)"
2656
+ ];
2657
+ const staged = document.documentElement.getAttribute(MEDIA_STAGE);
2658
+ if (staged !== null) {
2659
+ const readings = staged.split("").map((value) => value === "1");
2660
+ await sendProtocol("Emulation.setEmulatedMedia", {
2661
+ media: readings[0] ? "print" : "screen",
2662
+ features: [
2663
+ {
2664
+ name: "prefers-reduced-motion",
2665
+ value: readings[1] ? "reduce" : "no-preference"
2666
+ },
2667
+ {
2668
+ name: "prefers-color-scheme",
2669
+ value: readings[2] ? "dark" : "light"
2670
+ },
2671
+ {
2672
+ name: "forced-colors",
2673
+ value: readings[3] ? "active" : "none"
2674
+ }
2675
+ ]
2676
+ });
2677
+ try {
2678
+ await Promise.all(queries.map((query, index) => waitForCondition(query, async () => {
2679
+ await waitForFrame();
2680
+ return matchMedia(query).matches === readings[index];
2681
+ })));
2682
+ } catch (cause) {
2683
+ throw new Error("Media emulation did not clear from the tester", { cause });
2684
+ }
2685
+ document.documentElement.removeAttribute(MEDIA_STAGE);
2686
+ return;
2687
+ }
2688
+ await sendProtocol("Emulation.setEmulatedMedia", {
2689
+ media: "",
2690
+ features: []
2691
+ });
2692
+ let previous = queries.map((query) => matchMedia(query).matches);
2693
+ try {
2694
+ await waitForCondition("media emulation cleared", async () => {
2695
+ await waitForFrame();
2696
+ const readings = queries.map((query) => matchMedia(query).matches);
2697
+ const stable = readings.every((reading, index) => reading === previous[index]);
2698
+ previous = readings;
2699
+ return stable;
2700
+ });
2701
+ } catch (cause) {
2702
+ throw new Error("Media emulation did not clear from the tester", { cause });
2703
+ }
2704
+ }
2705
+ /**
2129
2706
  * Shoots one frame at one viewport size and proves the file on disk holds this run's bytes.
2130
2707
  *
2131
2708
  * @param options - The path to write, the viewport to shoot at, and the element to shoot.
@@ -2954,6 +3531,6 @@ function createHarness(options) {
2954
3531
  };
2955
3532
  }
2956
3533
  //#endregion
2957
- export { ACCESSIBLE_ROLES, CANVAS_COLOR, CAPTURE_PANE, CAPTURE_STAGINGS, CONTENT_ROLES, FIELD_ROLES, FOCUSABLE_SELECTOR, HEADER_ROLES, IMPLICIT_ROLES, blendColor, build, buildCensus, buildContrast, buildDenial, buildEscapes, captureFrame, clearStorage, clickAccessible, clickAccessibleWithin, clickDisclosure, commitInput, computeNamePattern, createChannel, createDragEvent, createHarness, createJournal, createPointerEvent, createPortfolio, createStorage, describeFocus, describeTree, expandCaptures, extractOrphans, extractStyles, fillAccessible, findKeyframes, findRule, isOutsideViewport, isReachable, isRendered, matchesColor, measureContent, measureContrast, measureLuminance, mount, parseCSSColor, parseColor, pressKeys, readBackdrop, readCascade, readCensus, readClasses, readContrast, readFocus, readFrame, readHit, readLayers, readName, readPage, readPerception, readPixels, readRefusal, readRing, readRole, readRootToken, readRows, readRules, readStates, readStyle, readText, readToken, readValue, releasePane, removeDatabase, render, resolveAccessible, resolveRendered, stagePane, traverseAccessible, typeAccessible, typeInput, waitForAnimations, waitForFrame, waitForState };
3534
+ export { ACCESSIBLE_ROLES, CANVAS_COLOR, CAPTURE_PANE, CAPTURE_STAGINGS, CONTENT_ROLES, FIELD_ROLES, FOCUSABLE_SELECTOR, HEADER_ROLES, IMPLICIT_ROLES, MEDIA_STAGE, POINTER_HOLD, blendColor, build, buildCensus, buildContrast, buildDenial, buildEscapes, captureFrame, clearStorage, clickAccessible, clickAccessibleWithin, clickDisclosure, commitInput, computeNamePattern, convertA98RGB, convertDisplayP3, convertLab, convertLinearSRGB, convertOKLab, convertProPhotoRGB, convertRec2020, convertSRGB, convertXYZD50, convertXYZD65, createChannel, createDragEvent, createHarness, createJournal, createPointerEvent, createPortfolio, createStorage, describeFocus, describeTree, expandCaptures, extractOrphans, extractStyles, fillAccessible, findKeyframes, findRule, holdAccessible, hoverAccessible, isOutsideViewport, isReachable, isRendered, matchesColor, measureContent, measureContrast, measureLuminance, mount, parseCSSColor, parseColor, pressKeys, readBackdrop, readCascade, readCensus, readClasses, readContrast, readFocus, readFrame, readHit, readLayers, readName, readPage, readPerception, readPixels, readRefusal, readRing, readRole, readRootToken, readRows, readRules, readStates, readStyle, readText, readToken, readValue, releaseMedia, releasePane, releasePointer, removeDatabase, render, resolveAccessible, resolveRendered, sendProtocol, stageMedia, stagePane, traverseAccessible, typeAccessible, typeInput, waitForAnimations, waitForFrame, waitForState };
2958
3535
 
2959
3536
  //# sourceMappingURL=index.js.map