sitcod3 commited on
Commit
2daf8de
·
verified ·
1 Parent(s): 5144199

Upload folder using huggingface_hub (part 12)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. node_modules/@tanstack/virtual-core/LICENSE +21 -0
  2. node_modules/@tanstack/virtual-core/dist/esm/lazy-measurements.js +34 -0
  3. node_modules/@tanstack/virtual-core/dist/esm/lazy-measurements.js.map +1 -0
  4. node_modules/@tanstack/virtual-core/dist/esm/utils.d.ts +15 -0
  5. node_modules/@tanstack/virtual-core/dist/esm/utils.js +74 -0
  6. node_modules/@tanstack/virtual-core/dist/esm/utils.js.map +1 -0
  7. node_modules/@tanstack/virtual-core/package.json +56 -0
  8. node_modules/@tanstack/virtual-core/src/index.ts +2093 -0
  9. node_modules/@tanstack/virtual-core/src/lazy-measurements.ts +44 -0
  10. node_modules/@tanstack/virtual-core/src/utils.ts +109 -0
  11. node_modules/@testing-library/dom/LICENSE +20 -0
  12. node_modules/@testing-library/dom/README.md +402 -0
  13. node_modules/@testing-library/dom/dist/@testing-library/dom.cjs.js +0 -0
  14. node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js +2848 -0
  15. node_modules/@testing-library/dom/dist/@testing-library/dom.umd.js +0 -0
  16. node_modules/@testing-library/dom/dist/@testing-library/dom.umd.js.map +0 -0
  17. node_modules/@testing-library/dom/dist/@testing-library/dom.umd.min.js +0 -0
  18. node_modules/@testing-library/dom/dist/@testing-library/dom.umd.min.js.map +0 -0
  19. node_modules/@testing-library/dom/dist/DOMElementFilter.js +116 -0
  20. node_modules/@testing-library/dom/dist/config.js +67 -0
  21. node_modules/@testing-library/dom/dist/event-map.js +711 -0
  22. node_modules/@testing-library/dom/dist/events.js +140 -0
  23. node_modules/@testing-library/dom/dist/get-node-text.js +13 -0
  24. node_modules/@testing-library/dom/dist/get-queries-for-element.js +25 -0
  25. node_modules/@testing-library/dom/dist/get-user-code-frame.js +55 -0
  26. node_modules/@testing-library/dom/dist/helpers.js +69 -0
  27. node_modules/@testing-library/dom/dist/index.js +185 -0
  28. node_modules/@testing-library/dom/dist/label-helpers.js +64 -0
  29. node_modules/@testing-library/dom/dist/matches.js +92 -0
  30. node_modules/@testing-library/dom/dist/pretty-dom.js +96 -0
  31. node_modules/@testing-library/dom/dist/queries/all-utils.js +49 -0
  32. node_modules/@testing-library/dom/dist/queries/alt-text.js +24 -0
  33. node_modules/@testing-library/dom/dist/queries/display-value.js +40 -0
  34. node_modules/@testing-library/dom/dist/queries/index.js +93 -0
  35. node_modules/@testing-library/dom/dist/queries/label-text.js +133 -0
  36. node_modules/@testing-library/dom/dist/queries/placeholder-text.js +22 -0
  37. node_modules/@testing-library/dom/dist/queries/role.js +274 -0
  38. node_modules/@testing-library/dom/dist/queries/test-id.js +23 -0
  39. node_modules/@testing-library/dom/dist/queries/text.js +57 -0
  40. node_modules/@testing-library/dom/dist/queries/title.js +34 -0
  41. node_modules/@testing-library/dom/dist/query-helpers.js +141 -0
  42. node_modules/@testing-library/dom/dist/role-helpers.js +355 -0
  43. node_modules/@testing-library/dom/dist/screen.js +57 -0
  44. node_modules/@testing-library/dom/dist/suggestions.js +118 -0
  45. node_modules/@testing-library/dom/dist/wait-for-element-to-be-removed.js +52 -0
  46. node_modules/@testing-library/dom/dist/wait-for.js +173 -0
  47. node_modules/@testing-library/dom/package.json +120 -0
  48. node_modules/@testing-library/dom/types/config.d.ts +27 -0
  49. node_modules/@testing-library/dom/types/events.d.ts +118 -0
  50. node_modules/@testing-library/dom/types/get-node-text.d.ts +1 -0
node_modules/@tanstack/virtual-core/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2021-present Tanner Linsley
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
node_modules/@tanstack/virtual-core/dist/esm/lazy-measurements.js ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function createLazyMeasurementsView(count, flat, getItemKey) {
2
+ const cache = new Array(count);
3
+ return new Proxy(cache, {
4
+ get(target, prop, receiver) {
5
+ if (typeof prop === "string") {
6
+ const c = prop.charCodeAt(0);
7
+ if (c >= 48 && c <= 57) {
8
+ const i = +prop;
9
+ if (Number.isInteger(i) && i >= 0 && i < count) {
10
+ let v = target[i];
11
+ if (!v) {
12
+ const s = flat[i * 2];
13
+ v = target[i] = {
14
+ index: i,
15
+ key: getItemKey(i),
16
+ start: s,
17
+ size: flat[i * 2 + 1],
18
+ end: s + flat[i * 2 + 1],
19
+ lane: 0
20
+ };
21
+ }
22
+ return v;
23
+ }
24
+ }
25
+ if (prop === "length") return count;
26
+ }
27
+ return Reflect.get(target, prop, receiver);
28
+ }
29
+ });
30
+ }
31
+ export {
32
+ createLazyMeasurementsView
33
+ };
34
+ //# sourceMappingURL=lazy-measurements.js.map
node_modules/@tanstack/virtual-core/dist/esm/lazy-measurements.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"lazy-measurements.js","sources":["../../src/lazy-measurements.ts"],"sourcesContent":["// Lazy materialization for the lanes===1 fast path. Backed by a\n// Float64Array (stride 2: start, size, …); VirtualItems are constructed on\n// first indexed read and cached. Saves the per-item object allocation at\n// large list counts where most items are never visible.\n\nimport type { VirtualItem } from './index'\n\ntype Key = number | string | bigint\n\nexport function createLazyMeasurementsView(\n count: number,\n flat: Float64Array,\n getItemKey: (i: number) => Key,\n): Array<VirtualItem> {\n const cache: Array<VirtualItem | undefined> = new Array(count)\n return new Proxy(cache as any, {\n get(target, prop, receiver) {\n if (typeof prop === 'string') {\n // Cheap digit-prefix sniff before number coerce.\n const c = prop.charCodeAt(0)\n if (c >= 48 && c <= 57) {\n const i = +prop\n if (Number.isInteger(i) && i >= 0 && i < count) {\n let v = target[i]\n if (!v) {\n const s = flat[i * 2]!\n v = target[i] = {\n index: i,\n key: getItemKey(i),\n start: s,\n size: flat[i * 2 + 1]!,\n end: s + flat[i * 2 + 1]!,\n lane: 0,\n }\n }\n return v\n }\n }\n if (prop === 'length') return count\n }\n return Reflect.get(target, prop, receiver)\n },\n }) as Array<VirtualItem>\n}\n"],"names":[],"mappings":"AASO,SAAS,2BACd,OACA,MACA,YACoB;AACpB,QAAM,QAAwC,IAAI,MAAM,KAAK;AAC7D,SAAO,IAAI,MAAM,OAAc;AAAA,IAC7B,IAAI,QAAQ,MAAM,UAAU;AAC1B,UAAI,OAAO,SAAS,UAAU;AAE5B,cAAM,IAAI,KAAK,WAAW,CAAC;AAC3B,YAAI,KAAK,MAAM,KAAK,IAAI;AACtB,gBAAM,IAAI,CAAC;AACX,cAAI,OAAO,UAAU,CAAC,KAAK,KAAK,KAAK,IAAI,OAAO;AAC9C,gBAAI,IAAI,OAAO,CAAC;AAChB,gBAAI,CAAC,GAAG;AACN,oBAAM,IAAI,KAAK,IAAI,CAAC;AACpB,kBAAI,OAAO,CAAC,IAAI;AAAA,gBACd,OAAO;AAAA,gBACP,KAAK,WAAW,CAAC;AAAA,gBACjB,OAAO;AAAA,gBACP,MAAM,KAAK,IAAI,IAAI,CAAC;AAAA,gBACpB,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC;AAAA,gBACvB,MAAM;AAAA,cAAA;AAAA,YAEV;AACA,mBAAO;AAAA,UACT;AAAA,QACF;AACA,YAAI,SAAS,SAAU,QAAO;AAAA,MAChC;AACA,aAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,IAC3C;AAAA,EAAA,CACD;AACH;"}
node_modules/@tanstack/virtual-core/dist/esm/utils.d.ts ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export type NoInfer<A extends any> = [A][A extends any ? 0 : never];
2
+ export type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
3
+ export declare function memo<TDeps extends ReadonlyArray<any>, TResult>(getDeps: () => [...TDeps], fn: (...args: NoInfer<[...TDeps]>) => TResult, opts: {
4
+ key: false | string;
5
+ debug?: () => boolean;
6
+ onChange?: (result: TResult) => void;
7
+ initialDeps?: TDeps;
8
+ skipInitialOnChange?: boolean;
9
+ }): {
10
+ (): TResult;
11
+ updateDeps(newDeps: [...TDeps]): void;
12
+ };
13
+ export declare function notUndefined<T>(value: T | undefined, msg?: string): T;
14
+ export declare const approxEqual: (a: number, b: number) => boolean;
15
+ export declare const debounce: (targetWindow: Window & typeof globalThis, fn: Function, ms: number) => (this: any, ...args: Array<any>) => void;
node_modules/@tanstack/virtual-core/dist/esm/utils.js ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function memo(getDeps, fn, opts) {
2
+ let deps = opts.initialDeps ?? [];
3
+ let result;
4
+ let isInitial = true;
5
+ function memoizedFunction() {
6
+ var _a;
7
+ const debugEnabled = process.env.NODE_ENV !== "production" && !!opts.key && !!((_a = opts.debug) == null ? void 0 : _a.call(opts));
8
+ let depTime = 0;
9
+ if (debugEnabled) depTime = Date.now();
10
+ const newDeps = getDeps();
11
+ const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);
12
+ if (!depsChanged) {
13
+ return result;
14
+ }
15
+ deps = newDeps;
16
+ let resultTime = 0;
17
+ if (debugEnabled) resultTime = Date.now();
18
+ result = fn(...newDeps);
19
+ if (debugEnabled) {
20
+ const depEndTime = Math.round((Date.now() - depTime) * 100) / 100;
21
+ const resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100;
22
+ const resultFpsPercentage = resultEndTime / 16;
23
+ const pad = (str, num) => {
24
+ str = String(str);
25
+ while (str.length < num) {
26
+ str = " " + str;
27
+ }
28
+ return str;
29
+ };
30
+ console.info(
31
+ `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,
32
+ `
33
+ font-size: .6rem;
34
+ font-weight: bold;
35
+ color: hsl(${Math.max(
36
+ 0,
37
+ Math.min(120 - 120 * resultFpsPercentage, 120)
38
+ )}deg 100% 31%);`,
39
+ opts == null ? void 0 : opts.key
40
+ );
41
+ }
42
+ if ((opts == null ? void 0 : opts.onChange) && !(isInitial && opts.skipInitialOnChange)) {
43
+ opts.onChange(result);
44
+ }
45
+ isInitial = false;
46
+ return result;
47
+ }
48
+ memoizedFunction.updateDeps = (newDeps) => {
49
+ deps = newDeps;
50
+ };
51
+ return memoizedFunction;
52
+ }
53
+ function notUndefined(value, msg) {
54
+ if (value === void 0) {
55
+ throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ""}`);
56
+ } else {
57
+ return value;
58
+ }
59
+ }
60
+ const approxEqual = (a, b) => Math.abs(a - b) < 1.01;
61
+ const debounce = (targetWindow, fn, ms) => {
62
+ let timeoutId;
63
+ return function(...args) {
64
+ targetWindow.clearTimeout(timeoutId);
65
+ timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms);
66
+ };
67
+ };
68
+ export {
69
+ approxEqual,
70
+ debounce,
71
+ memo,
72
+ notUndefined
73
+ };
74
+ //# sourceMappingURL=utils.js.map
node_modules/@tanstack/virtual-core/dist/esm/utils.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends ReadonlyArray<any>, TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => boolean\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n skipInitialOnChange?: boolean\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n let isInitial = true\n\n function memoizedFunction(): TResult {\n // Debug-only timing. In production builds, `process.env.NODE_ENV !==\n // 'production'` is constant-folded to `false` by downstream minifiers\n // (Terser/esbuild/swc with `define`), which DCEs the entire block.\n const debugEnabled =\n process.env.NODE_ENV !== 'production' && !!opts.key && !!opts.debug?.()\n let depTime = 0\n if (debugEnabled) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime = 0\n if (debugEnabled) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (debugEnabled) {\n const depEndTime = Math.round((Date.now() - depTime) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n if (opts?.onChange && !(isInitial && opts.skipInitialOnChange)) {\n opts.onChange(result)\n }\n\n isInitial = false\n\n return result\n }\n\n // Attach updateDeps to the function itself\n memoizedFunction.updateDeps = (newDeps: [...TDeps]) => {\n deps = newDeps\n }\n\n return memoizedFunction\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1.01\n\nexport const debounce = (\n targetWindow: Window & typeof globalThis,\n fn: Function,\n ms: number,\n) => {\n let timeoutId: number\n return function (this: any, ...args: Array<any>) {\n targetWindow.clearTimeout(timeoutId)\n timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms)\n }\n}\n"],"names":[],"mappings":"AAIO,SAAS,KACd,SACA,IACA,MAOA;AACA,MAAI,OAAO,KAAK,eAAe,CAAA;AAC/B,MAAI;AACJ,MAAI,YAAY;AAEhB,WAAS,mBAA4B;AAfhC;AAmBH,UAAM,eACJ,QAAQ,IAAI,aAAa,gBAAgB,CAAC,CAAC,KAAK,OAAO,CAAC,GAAC,UAAK,UAAL;AAC3D,QAAI,UAAU;AACd,QAAI,aAAc,WAAU,KAAK,IAAA;AAEjC,UAAM,UAAU,QAAA;AAEhB,UAAM,cACJ,QAAQ,WAAW,KAAK,UACxB,QAAQ,KAAK,CAAC,KAAU,UAAkB,KAAK,KAAK,MAAM,GAAG;AAE/D,QAAI,CAAC,aAAa;AAChB,aAAO;AAAA,IACT;AAEA,WAAO;AAEP,QAAI,aAAa;AACjB,QAAI,aAAc,cAAa,KAAK,IAAA;AAEpC,aAAS,GAAG,GAAG,OAAO;AAEtB,QAAI,cAAc;AAChB,YAAM,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAW,GAAG,IAAI;AAC9D,YAAM,gBAAgB,KAAK,OAAO,KAAK,QAAQ,cAAc,GAAG,IAAI;AACpE,YAAM,sBAAsB,gBAAgB;AAE5C,YAAM,MAAM,CAAC,KAAsB,QAAgB;AACjD,cAAM,OAAO,GAAG;AAChB,eAAO,IAAI,SAAS,KAAK;AACvB,gBAAM,MAAM;AAAA,QACd;AACA,eAAO;AAAA,MACT;AAEA,cAAQ;AAAA,QACN,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;AAAA,QACnD;AAAA;AAAA;AAAA,yBAGiB,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,IAAI,MAAM,MAAM,qBAAqB,GAAG;AAAA,QAAA,CAC9C;AAAA,QACL,6BAAM;AAAA,MAAA;AAAA,IAEV;AAEA,SAAI,6BAAM,aAAY,EAAE,aAAa,KAAK,sBAAsB;AAC9D,WAAK,SAAS,MAAM;AAAA,IACtB;AAEA,gBAAY;AAEZ,WAAO;AAAA,EACT;AAGA,mBAAiB,aAAa,CAAC,YAAwB;AACrD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,aAAgB,OAAsB,KAAiB;AACrE,MAAI,UAAU,QAAW;AACvB,UAAM,IAAI,MAAM,uBAAuB,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE;AAAA,EAChE,OAAO;AACL,WAAO;AAAA,EACT;AACF;AAEO,MAAM,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;AAEhE,MAAM,WAAW,CACtB,cACA,IACA,OACG;AACH,MAAI;AACJ,SAAO,YAAwB,MAAkB;AAC/C,iBAAa,aAAa,SAAS;AACnC,gBAAY,aAAa,WAAW,MAAM,GAAG,MAAM,MAAM,IAAI,GAAG,EAAE;AAAA,EACpE;AACF;"}
node_modules/@tanstack/virtual-core/package.json ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "@tanstack/virtual-core",
3
+ "version": "3.17.7",
4
+ "description": "Headless UI for virtualizing scrollable elements in TS/JS + Frameworks",
5
+ "author": "Tanner Linsley",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/TanStack/virtual.git",
10
+ "directory": "packages/virtual-core"
11
+ },
12
+ "homepage": "https://tanstack.com/virtual",
13
+ "funding": {
14
+ "type": "github",
15
+ "url": "https://github.com/sponsors/tannerlinsley"
16
+ },
17
+ "keywords": [
18
+ "react",
19
+ "vue",
20
+ "solid",
21
+ "virtual",
22
+ "virtual-core",
23
+ "datagrid"
24
+ ],
25
+ "type": "module",
26
+ "types": "dist/esm/index.d.ts",
27
+ "main": "dist/cjs/index.cjs",
28
+ "module": "dist/esm/index.js",
29
+ "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/esm/index.d.ts",
33
+ "default": "./dist/esm/index.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/cjs/index.d.cts",
37
+ "default": "./dist/cjs/index.cjs"
38
+ }
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "sideEffects": false,
43
+ "files": [
44
+ "dist",
45
+ "src"
46
+ ],
47
+ "scripts": {
48
+ "clean": "premove ./dist ./coverage",
49
+ "test:eslint": "eslint ./src",
50
+ "test:types": "tsc",
51
+ "test:lib": "vitest",
52
+ "test:lib:dev": "pnpm run test:lib --watch",
53
+ "test:build": "publint --strict",
54
+ "build": "vite build"
55
+ }
56
+ }
node_modules/@tanstack/virtual-core/src/index.ts ADDED
@@ -0,0 +1,2093 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { createLazyMeasurementsView } from './lazy-measurements'
2
+ import { approxEqual, debounce, memo, notUndefined } from './utils'
3
+
4
+ // Browser-aware iOS detection. Programmatic `scrollTo`/`scrollTop` writes
5
+ // during a momentum-scroll cancel the momentum on iOS WebKit, so we defer
6
+ // scroll-position adjustments triggered by mid-scroll resizes until the
7
+ // scroll settles. SSR-safe (returns false when navigator is unavailable).
8
+ let _isIOSResult: boolean | undefined
9
+ const isIOSWebKit = (): boolean => {
10
+ if (_isIOSResult !== undefined) return _isIOSResult
11
+ if (typeof navigator === 'undefined') return (_isIOSResult = false)
12
+ if (/iP(hone|od|ad)/.test(navigator.userAgent)) return (_isIOSResult = true)
13
+ // iPadOS 13+ reports as MacIntel; touch-points distinguishes it from desktop.
14
+ const mtp = (navigator as Navigator & { maxTouchPoints?: number })
15
+ .maxTouchPoints
16
+ return (_isIOSResult =
17
+ navigator.platform === 'MacIntel' && mtp !== undefined && mtp > 0)
18
+ }
19
+
20
+ // Test hook: reset the iOS detection cache. Not exported.
21
+ export const _resetIOSDetectionForTests = () => {
22
+ _isIOSResult = undefined
23
+ }
24
+
25
+ export { approxEqual, debounce, memo, notUndefined } from './utils'
26
+ export type { NoInfer, PartialKeys } from './utils'
27
+
28
+ //
29
+
30
+ type ScrollDirection = 'forward' | 'backward'
31
+
32
+ type ScrollAlignment = 'start' | 'center' | 'end' | 'auto'
33
+
34
+ type ScrollBehavior = 'auto' | 'smooth' | 'instant'
35
+
36
+ type ScrollAnchor = 'start' | 'end'
37
+
38
+ type FollowOnAppend = boolean | ScrollBehavior
39
+
40
+ export interface ScrollToOptions {
41
+ align?: ScrollAlignment
42
+ behavior?: ScrollBehavior
43
+ }
44
+
45
+ type ScrollToOffsetOptions = ScrollToOptions
46
+
47
+ type ScrollToIndexOptions = ScrollToOptions
48
+
49
+ type ScrollToEndOptions = Pick<ScrollToOptions, 'behavior'>
50
+
51
+ export interface Range {
52
+ startIndex: number
53
+ endIndex: number
54
+ overscan: number
55
+ count: number
56
+ }
57
+
58
+ type Key = number | string | bigint
59
+
60
+ export interface VirtualItem {
61
+ key: Key
62
+ index: number
63
+ start: number
64
+ end: number
65
+ size: number
66
+ lane: number
67
+ }
68
+
69
+ export interface Rect {
70
+ width: number
71
+ height: number
72
+ }
73
+
74
+ //
75
+
76
+ const getRect = (element: HTMLElement): Rect => {
77
+ const { offsetWidth, offsetHeight } = element
78
+ return { width: offsetWidth, height: offsetHeight }
79
+ }
80
+
81
+ export const defaultKeyExtractor = (index: number) => index
82
+
83
+ export const defaultRangeExtractor = (range: Range) => {
84
+ const start = Math.max(range.startIndex - range.overscan, 0)
85
+ const end = Math.min(range.endIndex + range.overscan, range.count - 1)
86
+ const len = end - start + 1
87
+
88
+ const arr = new Array<number>(len)
89
+ for (let i = 0; i < len; i++) {
90
+ arr[i] = start + i
91
+ }
92
+ return arr
93
+ }
94
+
95
+ export const observeElementRect = <T extends Element>(
96
+ instance: Virtualizer<T, any>,
97
+ cb: (rect: Rect) => void,
98
+ ) => {
99
+ const element = instance.scrollElement
100
+ if (!element) {
101
+ return
102
+ }
103
+ const targetWindow = instance.targetWindow
104
+ if (!targetWindow) {
105
+ return
106
+ }
107
+
108
+ const handler = (rect: Rect) => {
109
+ const { width, height } = rect
110
+ cb({ width: Math.round(width), height: Math.round(height) })
111
+ }
112
+
113
+ handler(getRect(element as unknown as HTMLElement))
114
+
115
+ if (!targetWindow.ResizeObserver) {
116
+ return () => {}
117
+ }
118
+
119
+ const observer = new targetWindow.ResizeObserver((entries) => {
120
+ const run = () => {
121
+ const entry = entries[0]
122
+ if (entry?.borderBoxSize) {
123
+ const box = entry.borderBoxSize[0]
124
+ if (box) {
125
+ handler({ width: box.inlineSize, height: box.blockSize })
126
+ return
127
+ }
128
+ }
129
+ handler(getRect(element as unknown as HTMLElement))
130
+ }
131
+
132
+ instance.options.useAnimationFrameWithResizeObserver
133
+ ? requestAnimationFrame(run)
134
+ : run()
135
+ })
136
+
137
+ observer.observe(element, { box: 'border-box' })
138
+
139
+ return () => {
140
+ observer.unobserve(element)
141
+ }
142
+ }
143
+
144
+ const addEventListenerOptions = {
145
+ passive: true,
146
+ }
147
+
148
+ export const observeWindowRect = (
149
+ instance: Virtualizer<Window, any>,
150
+ cb: (rect: Rect) => void,
151
+ ) => {
152
+ const element = instance.scrollElement
153
+ if (!element) {
154
+ return
155
+ }
156
+
157
+ const handler = () => {
158
+ cb({ width: element.innerWidth, height: element.innerHeight })
159
+ }
160
+ handler()
161
+
162
+ element.addEventListener('resize', handler, addEventListenerOptions)
163
+
164
+ return () => {
165
+ element.removeEventListener('resize', handler)
166
+ }
167
+ }
168
+
169
+ const supportsScrollend =
170
+ typeof window == 'undefined' ? true : 'onscrollend' in window
171
+
172
+ type ObserveOffsetCallBack = (offset: number, isScrolling: boolean) => void
173
+
174
+ // Shared core: both element and window variants attach scroll/scrollend
175
+ // listeners with the same lifecycle; they only differ in how to read the
176
+ // current offset from the scroll target.
177
+ const observeOffset = <T extends Element | Window>(
178
+ instance: Virtualizer<T, any>,
179
+ cb: ObserveOffsetCallBack,
180
+ readOffset: (target: T) => number,
181
+ ) => {
182
+ const element = instance.scrollElement
183
+ if (!element) {
184
+ return
185
+ }
186
+ const targetWindow = instance.targetWindow
187
+ if (!targetWindow) {
188
+ return
189
+ }
190
+
191
+ const registerScrollendEvent =
192
+ instance.options.useScrollendEvent && supportsScrollend
193
+
194
+ let offset = 0
195
+ const fallback = registerScrollendEvent
196
+ ? null
197
+ : debounce(
198
+ targetWindow,
199
+ () => cb(offset, false),
200
+ instance.options.isScrollingResetDelay,
201
+ )
202
+
203
+ const createHandler = (isScrolling: boolean) => () => {
204
+ offset = readOffset(element)
205
+ fallback?.()
206
+ cb(offset, isScrolling)
207
+ }
208
+ const handler = createHandler(true)
209
+ const endHandler = createHandler(false)
210
+
211
+ element.addEventListener('scroll', handler, addEventListenerOptions)
212
+ if (registerScrollendEvent) {
213
+ element.addEventListener('scrollend', endHandler, addEventListenerOptions)
214
+ }
215
+ return () => {
216
+ element.removeEventListener('scroll', handler)
217
+ if (registerScrollendEvent) {
218
+ element.removeEventListener('scrollend', endHandler)
219
+ }
220
+ }
221
+ }
222
+
223
+ export const observeElementOffset = <T extends Element>(
224
+ instance: Virtualizer<T, any>,
225
+ cb: ObserveOffsetCallBack,
226
+ ) =>
227
+ observeOffset(instance, cb, (el) => {
228
+ const { horizontal, isRtl } = instance.options
229
+ return horizontal ? el.scrollLeft * ((isRtl && -1) || 1) : el.scrollTop
230
+ })
231
+
232
+ export const observeWindowOffset = (
233
+ instance: Virtualizer<Window, any>,
234
+ cb: ObserveOffsetCallBack,
235
+ ) =>
236
+ observeOffset(instance, cb, (win) =>
237
+ instance.options.horizontal ? win.scrollX : win.scrollY,
238
+ )
239
+
240
+ export const measureElement = <TItemElement extends Element>(
241
+ element: TItemElement,
242
+ entry: ResizeObserverEntry | undefined,
243
+ instance: Virtualizer<any, TItemElement>,
244
+ ) => {
245
+ // When useCachedMeasurements is enabled, return the cached size
246
+ // (or estimateSize as fallback) instead of measuring the DOM.
247
+ if (instance.options.useCachedMeasurements) {
248
+ const index = instance.indexFromElement(element)
249
+ const key = instance.options.getItemKey(index)
250
+ return (
251
+ instance.itemSizeCache.get(key) ?? instance.options.estimateSize(index)
252
+ )
253
+ }
254
+
255
+ if (entry?.borderBoxSize) {
256
+ const box = entry.borderBoxSize[0]
257
+ if (box) {
258
+ const size = Math.round(
259
+ box[instance.options.horizontal ? 'inlineSize' : 'blockSize'],
260
+ )
261
+ return size
262
+ }
263
+ }
264
+
265
+ // When called without a ResizeObserverEntry (sync measurement path),
266
+ // return the previously measured size if available. This avoids a
267
+ // synchronous layout read (offsetWidth/offsetHeight) on re-renders.
268
+ // The ResizeObserver is already observing the element and will deliver
269
+ // the accurate size asynchronously if it changed.
270
+ // Users who need synchronous DOM reads can provide a custom measureElement.
271
+ if (!entry) {
272
+ const index = instance.indexFromElement(element)
273
+ const key = instance.options.getItemKey(index)
274
+ const cachedSize = instance.itemSizeCache.get(key)
275
+ if (cachedSize !== undefined) {
276
+ return cachedSize
277
+ }
278
+ }
279
+
280
+ return (element as unknown as HTMLElement)[
281
+ instance.options.horizontal ? 'offsetWidth' : 'offsetHeight'
282
+ ]
283
+ }
284
+
285
+ const scrollWithAdjustments = (
286
+ offset: number,
287
+ {
288
+ adjustments = 0,
289
+ behavior,
290
+ }: { adjustments?: number; behavior?: ScrollBehavior },
291
+ instance: Virtualizer<any, any>,
292
+ ) => {
293
+ instance.scrollElement?.scrollTo?.({
294
+ [instance.options.horizontal ? 'left' : 'top']: offset + adjustments,
295
+ behavior,
296
+ })
297
+ }
298
+
299
+ export const windowScroll: <T extends Window>(
300
+ offset: number,
301
+ options: { adjustments?: number; behavior?: ScrollBehavior },
302
+ instance: Virtualizer<T, any>,
303
+ ) => void = scrollWithAdjustments
304
+
305
+ export const elementScroll: <T extends Element>(
306
+ offset: number,
307
+ options: { adjustments?: number; behavior?: ScrollBehavior },
308
+ instance: Virtualizer<T, any>,
309
+ ) => void = scrollWithAdjustments
310
+
311
+ type LaneAssignmentMode = 'estimate' | 'measured'
312
+
313
+ export interface VirtualizerOptions<
314
+ TScrollElement extends Element | Window,
315
+ TItemElement extends Element,
316
+ > {
317
+ // Required from the user
318
+ count: number
319
+ getScrollElement: () => TScrollElement | null
320
+ estimateSize: (index: number) => number
321
+
322
+ // Required from the framework adapter (but can be overridden)
323
+ scrollToFn: (
324
+ offset: number,
325
+ options: { adjustments?: number; behavior?: ScrollBehavior },
326
+ instance: Virtualizer<TScrollElement, TItemElement>,
327
+ ) => void
328
+ observeElementRect: (
329
+ instance: Virtualizer<TScrollElement, TItemElement>,
330
+ cb: (rect: Rect) => void,
331
+ ) => void | (() => void)
332
+ observeElementOffset: (
333
+ instance: Virtualizer<TScrollElement, TItemElement>,
334
+ cb: ObserveOffsetCallBack,
335
+ ) => void | (() => void)
336
+ // Optional
337
+ debug?: boolean
338
+ initialRect?: Rect
339
+ onChange?: (
340
+ instance: Virtualizer<TScrollElement, TItemElement>,
341
+ sync: boolean,
342
+ ) => void
343
+ measureElement?: (
344
+ element: TItemElement,
345
+ entry: ResizeObserverEntry | undefined,
346
+ instance: Virtualizer<TScrollElement, TItemElement>,
347
+ ) => number
348
+ overscan?: number
349
+ horizontal?: boolean
350
+ paddingStart?: number
351
+ paddingEnd?: number
352
+ scrollPaddingStart?: number
353
+ scrollPaddingEnd?: number
354
+ initialOffset?: number | (() => number)
355
+ getItemKey?: (index: number) => Key
356
+ rangeExtractor?: (range: Range) => Array<number>
357
+ scrollMargin?: number
358
+ gap?: number
359
+ indexAttribute?: string
360
+ initialMeasurementsCache?: Array<VirtualItem>
361
+ lanes?: number
362
+ anchorTo?: ScrollAnchor
363
+ followOnAppend?: FollowOnAppend
364
+ scrollEndThreshold?: number
365
+ isScrollingResetDelay?: number
366
+ useScrollendEvent?: boolean
367
+ enabled?: boolean
368
+ isRtl?: boolean
369
+ useAnimationFrameWithResizeObserver?: boolean
370
+ laneAssignmentMode?: LaneAssignmentMode
371
+ useCachedMeasurements?: boolean
372
+ }
373
+
374
+ type ScrollState = {
375
+ // what we want
376
+ index: number | null
377
+ align: ScrollAlignment
378
+ behavior: ScrollBehavior
379
+
380
+ // lifecycle
381
+ startedAt: number
382
+
383
+ // target tracking
384
+ lastTargetOffset: number
385
+
386
+ // settling
387
+ stableFrames: number
388
+ }
389
+
390
+ type PendingScrollAnchor = [
391
+ key: Key | null,
392
+ offset: number,
393
+ followOnAppend: ScrollBehavior | null,
394
+ anchorDelta: number,
395
+ ]
396
+
397
+ export class Virtualizer<
398
+ TScrollElement extends Element | Window,
399
+ TItemElement extends Element,
400
+ > {
401
+ private unsubs: Array<void | (() => void)> = []
402
+ options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>
403
+ scrollElement: TScrollElement | null = null
404
+ targetWindow: (Window & typeof globalThis) | null = null
405
+ isScrolling = false
406
+ private scrollState: ScrollState | null = null
407
+ measurementsCache: Array<VirtualItem> = []
408
+ // Flat backing store for the lanes===1 fast path: [start_0, size_0, start_1, size_1, ...].
409
+ // null until the first single-lane build; reused (and grown) across rebuilds.
410
+ private _flatMeasurements: Float64Array | null = null
411
+ itemSizeCache = new Map<Key, number>()
412
+ private itemSizeCacheVersion = 0
413
+ private laneAssignments = new Map<number, number>() // index → lane cache
414
+ // Earliest index dirtied since last getMeasurements() rebuild, or null.
415
+ private pendingMin: number | null = null
416
+ private prevLanes: number | undefined = undefined
417
+ private lanesChangedFlag = false
418
+ private lanesSettling = false
419
+ private pendingScrollAnchor: PendingScrollAnchor | null = null
420
+ scrollRect: Rect | null = null
421
+ scrollOffset: number | null = null
422
+ scrollDirection: ScrollDirection | null = null
423
+ scrollAdjustments = 0
424
+ // Sum of size-change deltas above-viewport that were skipped during
425
+ // iOS momentum scroll (writing scrollTop mid-momentum cancels it).
426
+ // Flushed in a single scrollTo when iOS is fully settled.
427
+ private _iosDeferredAdjustment = 0
428
+ // Touch state. iOS WebKit cancels momentum when scrollTop is written, so
429
+ // we defer adjustments not only during `isScrolling` but also through the
430
+ // touchstart→touchend window (active drag) and a short tail after
431
+ // touchend (early-momentum window — iOS only fires touch events once at
432
+ // the start of momentum, so we use a timer rather than another event).
433
+ private _iosTouching = false
434
+ private _iosJustTouchEnded = false
435
+ private _iosTouchEndTimerId: number | null = null
436
+ // Subpixel reconciliation. Safari (and Chrome/Firefox under certain DPRs)
437
+ // round scrollTop/scrollLeft writes to integer pixels. If we wrote 12345.5
438
+ // but the browser reports back 12346, the next reconcileScroll sees a
439
+ // "target changed" and re-fires scrollTo — a feedback loop that the
440
+ // approxEqual(<1.01) tolerance otherwise absorbs as a workaround.
441
+ // By remembering the intended value of our most-recent self-driven
442
+ // scrollTo, we can match the browser's rounded read back to the intended
443
+ // value when the diff is < 1.5 px, distinguishing it from a real user
444
+ // scroll. The +0.5 over Math.abs lets us also absorb the +1 / -1 cases.
445
+ private _intendedScrollOffset: number | null = null
446
+ shouldAdjustScrollPositionOnItemSizeChange:
447
+ | undefined
448
+ | ((
449
+ item: VirtualItem,
450
+ delta: number,
451
+ instance: Virtualizer<TScrollElement, TItemElement>,
452
+ ) => boolean)
453
+ elementsCache = new Map<Key, TItemElement>()
454
+ private now = () => this.targetWindow?.performance?.now?.() ?? Date.now()
455
+ private observer = (() => {
456
+ let _ro: ResizeObserver | null = null
457
+
458
+ const get = () => {
459
+ if (_ro) {
460
+ return _ro
461
+ }
462
+
463
+ if (!this.targetWindow || !this.targetWindow.ResizeObserver) {
464
+ return null
465
+ }
466
+
467
+ return (_ro = new this.targetWindow.ResizeObserver((entries) => {
468
+ entries.forEach((entry) => {
469
+ const run = () => {
470
+ const node = entry.target as TItemElement
471
+ const index = this.indexFromElement(node)
472
+
473
+ if (!node.isConnected) {
474
+ this.observer.unobserve(node)
475
+ // Find the cache entry pointing to this exact node and remove
476
+ // it. We can't call getItemKey(index) here because items may
477
+ // have been removed since this node was rendered — the index
478
+ // could be stale and out-of-bounds in the user's data array
479
+ // (regression test in e2e/.../stale-index.spec.ts, fix #1148).
480
+ // The === comparison naturally handles the React-replaced-
481
+ // a-node-for-the-same-key case: that entry now points to a
482
+ // different node, so this loop won't match.
483
+ for (const [cacheKey, cachedNode] of this.elementsCache) {
484
+ if (cachedNode === node) {
485
+ this.elementsCache.delete(cacheKey)
486
+ break
487
+ }
488
+ }
489
+ return
490
+ }
491
+
492
+ if (this.shouldMeasureDuringScroll(index)) {
493
+ this.resizeItem(
494
+ index,
495
+ this.options.measureElement(node, entry, this),
496
+ )
497
+ }
498
+ }
499
+ this.options.useAnimationFrameWithResizeObserver
500
+ ? requestAnimationFrame(run)
501
+ : run()
502
+ })
503
+ }))
504
+ }
505
+
506
+ return {
507
+ disconnect: () => {
508
+ get()?.disconnect()
509
+ _ro = null
510
+ },
511
+ observe: (target: Element) =>
512
+ get()?.observe(target, { box: 'border-box' }),
513
+ unobserve: (target: Element) => get()?.unobserve(target),
514
+ }
515
+ })()
516
+ range: { startIndex: number; endIndex: number } | null = null
517
+
518
+ constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {
519
+ this.setOptions(opts)
520
+ }
521
+
522
+ setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {
523
+ // Skip `{...defaults, ...opts}` because explicit `undefined` values in
524
+ // opts would override defaults with `undefined`.
525
+ const merged = {
526
+ debug: false,
527
+ initialOffset: 0,
528
+ overscan: 1,
529
+ paddingStart: 0,
530
+ paddingEnd: 0,
531
+ scrollPaddingStart: 0,
532
+ scrollPaddingEnd: 0,
533
+ horizontal: false,
534
+ getItemKey: defaultKeyExtractor,
535
+ rangeExtractor: defaultRangeExtractor,
536
+ onChange: () => {},
537
+ measureElement,
538
+ initialRect: { width: 0, height: 0 },
539
+ scrollMargin: 0,
540
+ gap: 0,
541
+ indexAttribute: 'data-index',
542
+ initialMeasurementsCache: [],
543
+ lanes: 1,
544
+ anchorTo: 'start',
545
+ followOnAppend: false,
546
+ scrollEndThreshold: 1,
547
+ isScrollingResetDelay: 150,
548
+ enabled: true,
549
+ isRtl: false,
550
+ useScrollendEvent: false,
551
+ useAnimationFrameWithResizeObserver: false,
552
+ laneAssignmentMode: 'estimate',
553
+ useCachedMeasurements: false,
554
+ } as unknown as Required<VirtualizerOptions<TScrollElement, TItemElement>>
555
+
556
+ for (const key in opts) {
557
+ const v = (opts as any)[key]
558
+ if (v !== undefined) (merged as any)[key] = v
559
+ }
560
+
561
+ const prevOptions = this.options as
562
+ | Required<VirtualizerOptions<TScrollElement, TItemElement>>
563
+ | undefined
564
+ let anchor: [Key, number] | null = null
565
+ let followOnAppend: ScrollBehavior | null = null
566
+ let edgeKeysChanged = false
567
+
568
+ if (
569
+ prevOptions !== undefined &&
570
+ prevOptions.enabled &&
571
+ merged.enabled &&
572
+ merged.anchorTo === 'end' &&
573
+ this.scrollElement !== null
574
+ ) {
575
+ const prevCount = prevOptions.count
576
+ const nextCount = merged.count
577
+ const measurements = this.getMeasurements()
578
+ const prevFirstKey =
579
+ prevCount > 0
580
+ ? (measurements[0]?.key ?? prevOptions.getItemKey(0))
581
+ : null
582
+ const prevLastKey =
583
+ prevCount > 0
584
+ ? (measurements[prevCount - 1]?.key ??
585
+ prevOptions.getItemKey(prevCount - 1))
586
+ : null
587
+ const didCountChange = nextCount !== prevCount
588
+ const didEdgeKeysChange =
589
+ didCountChange ||
590
+ (prevCount > 0 &&
591
+ nextCount > 0 &&
592
+ (merged.getItemKey(0) !== prevFirstKey ||
593
+ merged.getItemKey(nextCount - 1) !== prevLastKey))
594
+
595
+ if (didEdgeKeysChange) {
596
+ edgeKeysChanged = true
597
+ const item =
598
+ prevCount > 0
599
+ ? (this.getVirtualItemForOffset(this.getScrollOffset()) ??
600
+ measurements[0])
601
+ : null
602
+
603
+ if (item) {
604
+ anchor = [item.key, this.getScrollOffset() - item.start]
605
+ }
606
+
607
+ const behavior =
608
+ merged.followOnAppend === true
609
+ ? 'auto'
610
+ : merged.followOnAppend || null
611
+
612
+ if (
613
+ behavior &&
614
+ nextCount > prevCount &&
615
+ this.isAtEnd(prevOptions.scrollEndThreshold) &&
616
+ (prevCount === 0 || merged.getItemKey(nextCount - 1) !== prevLastKey)
617
+ ) {
618
+ followOnAppend = behavior
619
+ }
620
+ }
621
+ }
622
+
623
+ this.options = merged
624
+
625
+ // When edge keys changed (prepend, trim, reorder, etc.) the key→index
626
+ // mapping has shifted. Force a full measurement rebuild so the anchor
627
+ // resolution below reads positions from the new layout, not the stale
628
+ // memoised cache. Without this, a stable `getItemKey` reference +
629
+ // unchanged `count` would let getMeasurements() return the old layout.
630
+ if (edgeKeysChanged) {
631
+ this.pendingMin = 0
632
+ this.itemSizeCacheVersion++
633
+ }
634
+
635
+ // Eagerly adjust scrollOffset so the virtualizer computes the correct
636
+ // visible range during the current render pass — before _willUpdate
637
+ // syncs the DOM scroll position in a layout effect. Without this,
638
+ // the virtualizer would render the wrong items for one frame (the
639
+ // estimate-based positions are stale) and then correct in the next
640
+ // frame, producing a visible "jump" on prepend with dynamic sizes.
641
+ let anchorResolved = false
642
+ let anchorDelta = 0
643
+ if (anchor && this.scrollOffset !== null) {
644
+ const [anchorKey, anchorOffset] = anchor
645
+ const newMeasurements = this.getMeasurements()
646
+ const { count, getItemKey } = this.options
647
+ let idx = 0
648
+ while (idx < count && getItemKey(idx) !== anchorKey) {
649
+ idx++
650
+ }
651
+ if (idx < count) {
652
+ const anchorItem = newMeasurements[idx]
653
+ if (anchorItem) {
654
+ // Clamp to the reachable range's lower bound — anchorOffset may
655
+ // have been derived from a transiently negative scrollOffset
656
+ // (rubber-band), and a negative tracked offset never self-heals
657
+ // when the element cannot scroll (#1229).
658
+ const newOffset = Math.max(0, anchorItem.start + anchorOffset)
659
+ if (newOffset !== this.scrollOffset) {
660
+ anchorDelta = newOffset - this.scrollOffset
661
+ this.scrollOffset = newOffset
662
+ anchorResolved = true
663
+ }
664
+ }
665
+ }
666
+ }
667
+
668
+ if (anchorResolved || followOnAppend) {
669
+ this.pendingScrollAnchor = [
670
+ anchorResolved ? anchor![0] : null,
671
+ anchorResolved ? anchor![1] : 0,
672
+ followOnAppend,
673
+ anchorDelta,
674
+ ]
675
+ }
676
+ }
677
+
678
+ private notify = (sync: boolean) => {
679
+ this.options.onChange?.(this, sync)
680
+ }
681
+
682
+ // Returns `true` when it performed a synchronous `scrollTop` write this
683
+ // tick, `false` when the delta was zero or the write was deferred (iOS).
684
+ // `resizeItem` uses that to decide whether the follow-up `notify` must be
685
+ // synchronous so the grown transforms commit in the same paint (#1227).
686
+ private applyScrollAdjustment(
687
+ delta: number,
688
+ behavior?: ScrollBehavior,
689
+ ): boolean {
690
+ if (delta === 0) return false
691
+
692
+ if (process.env.NODE_ENV !== 'production' && this.options.debug) {
693
+ console.info('correction', delta)
694
+ }
695
+
696
+ if (
697
+ isIOSWebKit() &&
698
+ (this.isScrolling || this._iosTouching || this._iosJustTouchEnded)
699
+ ) {
700
+ this._iosDeferredAdjustment += delta
701
+ return false
702
+ } else {
703
+ this._scrollToOffset(this.getScrollOffset(), {
704
+ adjustments: (this.scrollAdjustments += delta),
705
+ behavior,
706
+ })
707
+ // Eagerly carry the intended target in `scrollOffset` so callers that
708
+ // read it before the next scroll event — notably the next `resizeItem`
709
+ // tick's `getVirtualDistanceFromEnd()` / `wasAtEnd` check — see the
710
+ // post-adjustment position even when the DOM `scrollTop` write was
711
+ // clamped because the consumer hasn't grown the sizer yet (`notify()`
712
+ // runs after this in `resizeItem`). Same idea as the eager
713
+ // `scrollOffset` adjustment for prepend in `setOptions` (#1176). The
714
+ // adjustment is now baked into `scrollOffset`, so zero
715
+ // `scrollAdjustments` to keep their sum invariant.
716
+ if (this.scrollOffset !== null) {
717
+ this.scrollOffset += this.scrollAdjustments
718
+ // Clamp only the lower bound: a negative offset is unreachable, and
719
+ // on an unscrollable element (content fits the viewport) no scroll
720
+ // event ever fires to correct it, permanently skewing
721
+ // getDistanceFromEnd() and wedging _flushIosDeferredIfReady (#1229).
722
+ // Upper-bound overflow stays untouched — it is transiently
723
+ // legitimate mid-prepend while the consumer's sizer catches up.
724
+ if (this.scrollOffset < 0) this.scrollOffset = 0
725
+ this.scrollAdjustments = 0
726
+ }
727
+ return true
728
+ }
729
+ }
730
+
731
+ private maybeNotify = memo(
732
+ () => {
733
+ this.calculateRange()
734
+
735
+ return [
736
+ this.isScrolling,
737
+ this.range ? this.range.startIndex : null,
738
+ this.range ? this.range.endIndex : null,
739
+ ]
740
+ },
741
+ (isScrolling) => {
742
+ this.notify(isScrolling)
743
+ },
744
+ {
745
+ key: process.env.NODE_ENV !== 'production' && 'maybeNotify',
746
+ debug: () => this.options.debug,
747
+ initialDeps: [
748
+ this.isScrolling,
749
+ this.range ? this.range.startIndex : null,
750
+ this.range ? this.range.endIndex : null,
751
+ ] as [boolean, number | null, number | null],
752
+ },
753
+ )
754
+
755
+ private cleanup = () => {
756
+ this.unsubs.filter(Boolean).forEach((d) => d!())
757
+ this.unsubs = []
758
+ this.observer.disconnect()
759
+ if (this.rafId != null && this.targetWindow) {
760
+ this.targetWindow.cancelAnimationFrame(this.rafId)
761
+ this.rafId = null
762
+ }
763
+ this.scrollState = null
764
+ // The iOS gesture/deferral state is scoped to the current scroll
765
+ // element: the touch listeners that maintain it were just removed, and
766
+ // an in-flight touch keeps targeting the old element (implicit touch
767
+ // capture), so the new element never reports it. Carrying the state
768
+ // over would replay a stale deferred delta on the new element's first
769
+ // flush, and a cleanup that lands mid-touch or inside the post-touchend
770
+ // grace window would strand _iosTouching / _iosJustTouchEnded as true
771
+ // (the listener unsub clears the grace timer, and with it the only
772
+ // pending reset of the flag), deferring every adjustment on the new
773
+ // element until its next touch cycle.
774
+ this._iosDeferredAdjustment = 0
775
+ this._iosTouching = false
776
+ this._iosJustTouchEnded = false
777
+ this.scrollElement = null
778
+ this.targetWindow = null
779
+ }
780
+
781
+ _didMount = () => {
782
+ return () => {
783
+ this.cleanup()
784
+ }
785
+ }
786
+
787
+ _willUpdate = () => {
788
+ const scrollElement = this.options.enabled
789
+ ? this.options.getScrollElement()
790
+ : null
791
+
792
+ if (this.scrollElement !== scrollElement) {
793
+ this.cleanup()
794
+
795
+ if (!scrollElement) {
796
+ this.maybeNotify()
797
+ return
798
+ }
799
+
800
+ this.scrollElement = scrollElement
801
+
802
+ if (this.scrollElement && 'ownerDocument' in this.scrollElement) {
803
+ this.targetWindow = this.scrollElement.ownerDocument.defaultView
804
+ } else {
805
+ this.targetWindow = this.scrollElement?.window ?? null
806
+ }
807
+
808
+ this.elementsCache.forEach((cached) => {
809
+ this.observer.observe(cached)
810
+ })
811
+
812
+ this.unsubs.push(
813
+ this.options.observeElementRect(this, (rect) => {
814
+ this.scrollRect = rect
815
+ this.maybeNotify()
816
+ }),
817
+ )
818
+
819
+ this.unsubs.push(
820
+ this.options.observeElementOffset(this, (offset, isScrolling) => {
821
+ // A scroll event that reports movement but lands on the offset we
822
+ // already hold — and isn't a self-write read-back — is a spurious
823
+ // no-op re-emit that Safari/Firefox fire after a re-render's layout
824
+ // (Chrome doesn't). Treating it as scrolling re-arms `isScrolling`,
825
+ // which forces a render that triggers another such event: an
826
+ // infinite re-render loop. Ignore it. (Self-writes are handled by
827
+ // the `_intendedScrollOffset` reconciliation just below.)
828
+ if (
829
+ isScrolling &&
830
+ this._intendedScrollOffset === null &&
831
+ offset === this.scrollOffset
832
+ ) {
833
+ return
834
+ }
835
+
836
+ // If this scroll event looks like the browser's read-back of a
837
+ // value we just wrote, prefer our intended (sub-pixel-accurate)
838
+ // value over the browser's rounded one. The 1.5 px tolerance is
839
+ // tight enough to avoid mistaking a real user scroll for a
840
+ // self-write — by the time the user has moved 1.5 px, the
841
+ // intended value will already have been consumed by a prior
842
+ // scroll event and cleared.
843
+ if (
844
+ this._intendedScrollOffset !== null &&
845
+ Math.abs(offset - this._intendedScrollOffset) < 1.5
846
+ ) {
847
+ offset = this._intendedScrollOffset
848
+ }
849
+ this._intendedScrollOffset = null
850
+
851
+ this.scrollAdjustments = 0
852
+ // If the offset hasn't moved, this is the echo of our own
853
+ // adjustment write — `applyScrollAdjustment` already folded it
854
+ // into `scrollOffset`. There's no direction to infer, so leave
855
+ // it alone; a real gesture always moves the offset.
856
+ const prevOffset = this.getScrollOffset()
857
+ this.scrollDirection = isScrolling
858
+ ? prevOffset === offset
859
+ ? this.scrollDirection
860
+ : prevOffset < offset
861
+ ? 'forward'
862
+ : 'backward'
863
+ : null
864
+ this.scrollOffset = offset
865
+ this.isScrolling = isScrolling
866
+
867
+ // Flush deferred iOS adjustments if we're now fully settled.
868
+ // "Fully settled" means: not actively scrolling, no finger on
869
+ // screen, and the post-touchend grace window has expired.
870
+ this._flushIosDeferredIfReady()
871
+
872
+ if (this.scrollState) {
873
+ this.scheduleScrollReconcile()
874
+ }
875
+ this.maybeNotify()
876
+ }),
877
+ )
878
+
879
+ // Touch event listeners (iOS-aware deferral). We attach unconditionally
880
+ // — the listeners are passive and cheap; on non-touch devices they
881
+ // simply never fire. The gating by isIOSWebKit() lives in resizeItem
882
+ // and _flushIosDeferredIfReady so we only burn the path on iOS.
883
+ if ('addEventListener' in this.scrollElement) {
884
+ const scrollEl = this.scrollElement as unknown as EventTarget
885
+ const onTouchStart = () => {
886
+ this._iosTouching = true
887
+ this._iosJustTouchEnded = false
888
+ if (this._iosTouchEndTimerId !== null && this.targetWindow != null) {
889
+ this.targetWindow.clearTimeout(this._iosTouchEndTimerId)
890
+ this._iosTouchEndTimerId = null
891
+ }
892
+ }
893
+ const onTouchEnd = () => {
894
+ this._iosTouching = false
895
+ if (!isIOSWebKit() || this.targetWindow == null) {
896
+ // Non-iOS: nothing more to track. Just clear the touching flag.
897
+ return
898
+ }
899
+ this._iosJustTouchEnded = true
900
+ // After ~150 ms with no scroll/touch events, momentum is done.
901
+ this._iosTouchEndTimerId = this.targetWindow.setTimeout(() => {
902
+ this._iosJustTouchEnded = false
903
+ this._iosTouchEndTimerId = null
904
+ // After the grace window, attempt to flush. The scroll event
905
+ // for momentum decay may have already fired before our timer.
906
+ this._flushIosDeferredIfReady()
907
+ }, 150)
908
+ }
909
+ scrollEl.addEventListener(
910
+ 'touchstart',
911
+ onTouchStart,
912
+ addEventListenerOptions,
913
+ )
914
+ scrollEl.addEventListener(
915
+ 'touchend',
916
+ onTouchEnd,
917
+ addEventListenerOptions,
918
+ )
919
+ this.unsubs.push(() => {
920
+ scrollEl.removeEventListener('touchstart', onTouchStart)
921
+ scrollEl.removeEventListener('touchend', onTouchEnd)
922
+ if (this._iosTouchEndTimerId !== null && this.targetWindow != null) {
923
+ this.targetWindow.clearTimeout(this._iosTouchEndTimerId)
924
+ this._iosTouchEndTimerId = null
925
+ }
926
+ })
927
+ }
928
+
929
+ this._scrollToOffset(this.getScrollOffset(), {
930
+ adjustments: undefined,
931
+ behavior: undefined,
932
+ })
933
+ }
934
+
935
+ const anchor = this.pendingScrollAnchor
936
+ this.pendingScrollAnchor = null
937
+
938
+ if (anchor && this.scrollElement && this.options.enabled) {
939
+ const [key, _offset, followOnAppend, anchorDelta] = anchor
940
+
941
+ if (key !== null && !followOnAppend) {
942
+ // scrollOffset was eagerly adjusted in setOptions so the
943
+ // virtualizer already computed the correct range during render.
944
+ // Now sync the browser's actual scroll position to match.
945
+ // Skip when followOnAppend is set — scrollToEnd will handle it.
946
+ //
947
+ // On iOS WebKit, writing scrollTop during touch/momentum cancels
948
+ // the in-flight scroll. Defer the DOM sync the same way
949
+ // applyScrollAdjustment does — accumulate the delta and let
950
+ // _flushIosDeferredIfReady handle it once the scroll settles.
951
+ if (
952
+ isIOSWebKit() &&
953
+ (this.isScrolling || this._iosTouching || this._iosJustTouchEnded)
954
+ ) {
955
+ if (anchorDelta !== 0) {
956
+ this._iosDeferredAdjustment += anchorDelta
957
+ }
958
+ } else {
959
+ this._scrollToOffset(this.getScrollOffset(), {
960
+ adjustments: undefined,
961
+ behavior: undefined,
962
+ })
963
+ }
964
+ }
965
+
966
+ if (followOnAppend) {
967
+ this.scrollToEnd({ behavior: followOnAppend })
968
+ }
969
+ }
970
+ }
971
+
972
+ // Apply any accumulated iOS-deferred scroll adjustment, but only when we're
973
+ // truly settled — not actively scrolling, not under an active touch, and
974
+ // past the post-touchend grace window. Called from the scroll callback
975
+ // and the touchend grace-timer.
976
+ private _flushIosDeferredIfReady = () => {
977
+ if (this._iosDeferredAdjustment === 0) return
978
+ if (this.isScrolling) return
979
+ if (this._iosTouching) return
980
+ if (this._iosJustTouchEnded) return
981
+ // Phase 2b: Safari elastic-overscroll (rubber-band) lets scrollTop go
982
+ // negative or beyond scrollHeight - clientHeight. Writing scrollTop
983
+ // while in that zone snaps the page back to the clamped value at the
984
+ // end of the bounce, often discarding the user's intent. Skip the
985
+ // flush; the next in-bounds scroll event will retry.
986
+ const cur = this.getScrollOffset()
987
+ const max = this.getMaxScrollOffset()
988
+ if (cur < 0 || cur > max) return
989
+ // At the end clamp the browser already absorbed a shrink above the
990
+ // viewport (it clamped scrollTop onto the new bottom), so replaying our
991
+ // deferred negative delta would lift the view off the bottom — drop it.
992
+ // Positive deltas still replay: growth above doesn't clamp. (#1233)
993
+ if (this._iosDeferredAdjustment < 0 && cur >= max - 1) {
994
+ this._iosDeferredAdjustment = 0
995
+ return
996
+ }
997
+ const delta = this._iosDeferredAdjustment
998
+ this._iosDeferredAdjustment = 0
999
+ // Roll the deferred delta into the running accumulator so any resize
1000
+ // landing between now and the resulting scroll event computes from the
1001
+ // post-flush offset rather than the stale one.
1002
+ this._scrollToOffset(cur, {
1003
+ adjustments: (this.scrollAdjustments += delta),
1004
+ behavior: undefined,
1005
+ })
1006
+ }
1007
+
1008
+ private rafId: number | null = null
1009
+ private scheduleScrollReconcile() {
1010
+ if (!this.targetWindow) {
1011
+ this.scrollState = null
1012
+ return
1013
+ }
1014
+ if (this.rafId != null) return
1015
+ this.rafId = this.targetWindow.requestAnimationFrame(() => {
1016
+ this.rafId = null
1017
+ this.reconcileScroll()
1018
+ })
1019
+ }
1020
+ private reconcileScroll() {
1021
+ if (!this.scrollState) return
1022
+
1023
+ const el = this.scrollElement
1024
+ if (!el) return
1025
+
1026
+ // Safety valve: bail out if reconciliation has been running too long
1027
+ const MAX_RECONCILE_MS = 5000
1028
+ if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {
1029
+ this.scrollState = null
1030
+ return
1031
+ }
1032
+
1033
+ const offsetInfo =
1034
+ this.scrollState.index != null
1035
+ ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align)
1036
+ : undefined
1037
+ const targetOffset = offsetInfo
1038
+ ? offsetInfo[0]
1039
+ : this.scrollState.lastTargetOffset
1040
+
1041
+ // Require one stable frame where target matches scroll offset.
1042
+ // approxEqual() already tolerates minor fluctuations, so one frame is sufficient
1043
+ // to confirm scroll has reached its target without premature cleanup.
1044
+ const STABLE_FRAMES = 1
1045
+
1046
+ const targetChanged = targetOffset !== this.scrollState.lastTargetOffset
1047
+
1048
+ if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {
1049
+ this.scrollState.stableFrames++
1050
+ if (this.scrollState.stableFrames >= STABLE_FRAMES) {
1051
+ // Final-pass exact landing. The reconcile-stable check uses a 1.01px
1052
+ // tolerance (approxEqual) so we don't fight subpixel browser rounding
1053
+ // during the converging phase. Once we're definitively settled,
1054
+ // commit the exact target so consumers calling scrollToIndex(N)
1055
+ // end up at the EXACT computed position of item N — matching
1056
+ // virtuoso's 0px landing accuracy rather than our prior 0.5-1px.
1057
+ if (this.getScrollOffset() !== targetOffset) {
1058
+ this._scrollToOffset(targetOffset, {
1059
+ adjustments: undefined,
1060
+ behavior: 'auto',
1061
+ })
1062
+ }
1063
+ this.scrollState = null
1064
+ return
1065
+ }
1066
+ } else {
1067
+ this.scrollState.stableFrames = 0
1068
+
1069
+ if (targetChanged) {
1070
+ // When the target moves during smooth scroll (because items came into
1071
+ // view and got measured, shifting positions), the original logic was
1072
+ // to immediately snap to 'auto' — visibly jarring on long
1073
+ // scroll-to-index calls. Now: keep smooth while we're still far
1074
+ // (more than a viewport) from the new target. Only fall back to
1075
+ // 'auto' for the final approach, so the user sees one continuous
1076
+ // motion that smoothly adjusts its endpoint as measurements arrive.
1077
+ const viewport = this.getSize() || 600
1078
+ const distance = Math.abs(targetOffset - this.getScrollOffset())
1079
+ const keepSmooth =
1080
+ this.scrollState.behavior === 'smooth' && distance > viewport
1081
+
1082
+ this.scrollState.lastTargetOffset = targetOffset
1083
+ if (!keepSmooth) {
1084
+ this.scrollState.behavior = 'auto'
1085
+ }
1086
+
1087
+ this._scrollToOffset(targetOffset, {
1088
+ adjustments: undefined,
1089
+ behavior: keepSmooth ? 'smooth' : 'auto',
1090
+ })
1091
+ }
1092
+ }
1093
+
1094
+ // Always reschedule while scrollState is active to guarantee
1095
+ // the safety valve timeout runs even if no scroll events fire
1096
+ // (e.g. no-op scrollToFn, detached element)
1097
+ this.scheduleScrollReconcile()
1098
+ }
1099
+
1100
+ private getSize = () => {
1101
+ if (!this.options.enabled) {
1102
+ this.scrollRect = null
1103
+ return 0
1104
+ }
1105
+
1106
+ this.scrollRect = this.scrollRect ?? this.options.initialRect
1107
+
1108
+ return this.scrollRect[this.options.horizontal ? 'width' : 'height']
1109
+ }
1110
+
1111
+ private getScrollOffset = () => {
1112
+ if (!this.options.enabled) {
1113
+ this.scrollOffset = null
1114
+ return 0
1115
+ }
1116
+
1117
+ this.scrollOffset =
1118
+ this.scrollOffset ??
1119
+ (typeof this.options.initialOffset === 'function'
1120
+ ? this.options.initialOffset()
1121
+ : this.options.initialOffset)
1122
+
1123
+ return this.scrollOffset
1124
+ }
1125
+
1126
+ private getMeasurementOptions = memo(
1127
+ () => [
1128
+ this.options.count,
1129
+ this.options.paddingStart,
1130
+ this.options.scrollMargin,
1131
+ this.options.getItemKey,
1132
+ this.options.enabled,
1133
+ this.options.lanes,
1134
+ this.options.laneAssignmentMode,
1135
+ this.options.gap,
1136
+ ],
1137
+ (
1138
+ count,
1139
+ paddingStart,
1140
+ scrollMargin,
1141
+ getItemKey,
1142
+ enabled,
1143
+ lanes,
1144
+ laneAssignmentMode,
1145
+ gap,
1146
+ ) => {
1147
+ const lanesChanged =
1148
+ this.prevLanes !== undefined && this.prevLanes !== lanes
1149
+
1150
+ if (lanesChanged) {
1151
+ // Set flag for getMeasurements to handle
1152
+ this.lanesChangedFlag = true
1153
+ }
1154
+
1155
+ this.prevLanes = lanes
1156
+ this.pendingMin = null
1157
+
1158
+ return {
1159
+ count,
1160
+ paddingStart,
1161
+ scrollMargin,
1162
+ getItemKey,
1163
+ enabled,
1164
+ lanes,
1165
+ laneAssignmentMode,
1166
+ gap,
1167
+ }
1168
+ },
1169
+ {
1170
+ key: false,
1171
+ },
1172
+ )
1173
+
1174
+ private getMeasurements = memo(
1175
+ () => [this.getMeasurementOptions(), this.itemSizeCacheVersion],
1176
+ (
1177
+ {
1178
+ count,
1179
+ paddingStart,
1180
+ scrollMargin,
1181
+ getItemKey,
1182
+ enabled,
1183
+ lanes,
1184
+ laneAssignmentMode,
1185
+ gap,
1186
+ },
1187
+ _itemSizeCacheVersion,
1188
+ ) => {
1189
+ const itemSizeCache = this.itemSizeCache
1190
+ if (!enabled) {
1191
+ this.measurementsCache = []
1192
+ this.itemSizeCache.clear()
1193
+ this.laneAssignments.clear()
1194
+ return []
1195
+ }
1196
+
1197
+ // Clean up stale lane cache entries when count decreases
1198
+ if (this.laneAssignments.size > count) {
1199
+ for (const index of this.laneAssignments.keys()) {
1200
+ if (index >= count) {
1201
+ this.laneAssignments.delete(index)
1202
+ }
1203
+ }
1204
+ }
1205
+
1206
+ // ✅ Force complete recalculation when lanes change
1207
+ if (this.lanesChangedFlag) {
1208
+ this.lanesChangedFlag = false // Reset immediately
1209
+ this.lanesSettling = true // Start settling period
1210
+ this.measurementsCache = []
1211
+ this.itemSizeCache.clear()
1212
+ this.laneAssignments.clear() // Clear lane cache for new lane count
1213
+ // Force min = 0 on the rebuild
1214
+ this.pendingMin = null
1215
+ }
1216
+
1217
+ // Don't restore from initialMeasurementsCache during lane changes
1218
+ // as it contains stale lane assignments from the previous lane count
1219
+ if (this.measurementsCache.length === 0 && !this.lanesSettling) {
1220
+ this.measurementsCache = this.options.initialMeasurementsCache
1221
+ this.measurementsCache.forEach((item) => {
1222
+ this.itemSizeCache.set(item.key, item.size)
1223
+ })
1224
+ }
1225
+
1226
+ // During lanes settling, ignore pendingMin to prevent repositioning
1227
+ const min = this.lanesSettling ? 0 : (this.pendingMin ?? 0)
1228
+ this.pendingMin = null
1229
+
1230
+ // ✅ End settling period when cache is fully built
1231
+ if (this.lanesSettling && this.measurementsCache.length === count) {
1232
+ this.lanesSettling = false
1233
+ }
1234
+
1235
+ // ─── Fast path: single-lane lazy materialization ────────────────────
1236
+ // For lanes === 1 (the default and most common case), skip the
1237
+ // per-item VirtualItem object allocation. We write start/size pairs
1238
+ // into a Float64Array and return a Proxy that builds VirtualItem
1239
+ // objects on demand (only the indices a consumer actually reads).
1240
+ //
1241
+ // At n=100k this drops cold-mount cost from ~2.5ms (eager object
1242
+ // allocation) to roughly the cost of a single typed-array fill.
1243
+ if (lanes === 1) {
1244
+ // Reuse flat backing if large enough; else grow (preserving data
1245
+ // before `min` to mirror the slice-and-rebuild contract).
1246
+ const need = count * 2
1247
+ let flat = this._flatMeasurements
1248
+ if (!flat || flat.length < need) {
1249
+ const next = new Float64Array(need)
1250
+ if (flat && min > 0) next.set(flat.subarray(0, min * 2))
1251
+ flat = next
1252
+ this._flatMeasurements = flat
1253
+ }
1254
+
1255
+ let runningStart: number
1256
+ if (min === 0) {
1257
+ runningStart = paddingStart + scrollMargin
1258
+ } else {
1259
+ // Continue from where we left off
1260
+ const prevIdx = min - 1
1261
+ runningStart = flat[prevIdx * 2]! + flat[prevIdx * 2 + 1]! + gap
1262
+ }
1263
+
1264
+ for (let i = min; i < count; i++) {
1265
+ const key = getItemKey(i)
1266
+ const measuredSize = itemSizeCache.get(key)
1267
+ const size =
1268
+ typeof measuredSize === 'number'
1269
+ ? measuredSize
1270
+ : this.options.estimateSize(i)
1271
+ flat[i * 2] = runningStart
1272
+ flat[i * 2 + 1] = size
1273
+ runningStart += size + gap
1274
+ }
1275
+
1276
+ const view = createLazyMeasurementsView(count, flat, getItemKey)
1277
+ this.measurementsCache = view
1278
+ return view
1279
+ }
1280
+
1281
+ const measurements = this.measurementsCache.slice(0, min)
1282
+
1283
+ // ✅ Performance: Track last item index per lane for O(1) lookup
1284
+ const laneLastIndex: Array<number | undefined> = new Array(lanes).fill(
1285
+ undefined,
1286
+ )
1287
+ // Running end position of each lane's last item, so the shortest lane
1288
+ // can be found with an O(lanes) argmin instead of the old backward walk
1289
+ // through `measurements` (getFurthestMeasurement). `filledLanes` tracks
1290
+ // how many lanes have at least one item, mirroring the previous
1291
+ // "all lanes seen → shortest lane, else i % lanes" branch.
1292
+ const laneEnds = new Float64Array(lanes)
1293
+ let filledLanes = 0
1294
+
1295
+ // Initialize from existing measurements (before min)
1296
+ for (let m = 0; m < min; m++) {
1297
+ const item = measurements[m]
1298
+ if (item) {
1299
+ if (laneLastIndex[item.lane] === undefined) filledLanes++
1300
+ laneLastIndex[item.lane] = m
1301
+ laneEnds[item.lane] = item.end
1302
+ }
1303
+ }
1304
+
1305
+ for (let i = min; i < count; i++) {
1306
+ const key = getItemKey(i)
1307
+
1308
+ // Check for cached lane assignment
1309
+ const cachedLane = this.laneAssignments.get(i)
1310
+ let lane: number
1311
+ let start: number
1312
+
1313
+ const shouldCacheLane =
1314
+ laneAssignmentMode === 'estimate' || itemSizeCache.has(key)
1315
+
1316
+ if (cachedLane !== undefined && this.options.lanes > 1) {
1317
+ // Use cached lane - O(1) lookup for previous item in same lane
1318
+ lane = cachedLane
1319
+ const prevIndex = laneLastIndex[lane]
1320
+ const prevInLane =
1321
+ prevIndex !== undefined ? measurements[prevIndex] : undefined
1322
+ start = prevInLane
1323
+ ? prevInLane.end + gap
1324
+ : paddingStart + scrollMargin
1325
+ } else if (filledLanes === lanes) {
1326
+ // No cache, every lane seeded: place in the shortest lane.
1327
+ // Read the running per-lane ends (O(lanes) argmin) instead of the
1328
+ // old backward scan. Tie-break on the lane's last-item index to
1329
+ // preserve the previous sort-by-(end, index) placement exactly.
1330
+ let bestLane = 0
1331
+ let bestEnd = laneEnds[0]!
1332
+ let bestIdx = laneLastIndex[0]!
1333
+ for (let l = 1; l < lanes; l++) {
1334
+ const e = laneEnds[l]!
1335
+ if (e < bestEnd || (e === bestEnd && laneLastIndex[l]! < bestIdx)) {
1336
+ bestLane = l
1337
+ bestEnd = e
1338
+ bestIdx = laneLastIndex[l]!
1339
+ }
1340
+ }
1341
+ lane = bestLane
1342
+ start = bestEnd + gap
1343
+
1344
+ if (shouldCacheLane) {
1345
+ this.laneAssignments.set(i, lane)
1346
+ }
1347
+ } else {
1348
+ // No cache and not every lane seeded yet — seed lanes in order,
1349
+ // matching the previous `i % lanes` fallback for the first row.
1350
+ lane = i % this.options.lanes
1351
+ start = paddingStart + scrollMargin
1352
+
1353
+ if (shouldCacheLane) {
1354
+ this.laneAssignments.set(i, lane)
1355
+ }
1356
+ }
1357
+
1358
+ const measuredSize = itemSizeCache.get(key)
1359
+ const size =
1360
+ typeof measuredSize === 'number'
1361
+ ? measuredSize
1362
+ : this.options.estimateSize(i)
1363
+
1364
+ const end = start + size
1365
+
1366
+ measurements[i] = {
1367
+ index: i,
1368
+ start,
1369
+ size,
1370
+ end,
1371
+ key,
1372
+ lane,
1373
+ }
1374
+
1375
+ // ✅ Performance: Update lane's last item index + running end
1376
+ if (laneLastIndex[lane] === undefined) filledLanes++
1377
+ laneLastIndex[lane] = i
1378
+ laneEnds[lane] = end
1379
+ }
1380
+
1381
+ this.measurementsCache = measurements
1382
+
1383
+ return measurements
1384
+ },
1385
+ {
1386
+ key: process.env.NODE_ENV !== 'production' && 'getMeasurements',
1387
+ debug: () => this.options.debug,
1388
+ },
1389
+ )
1390
+
1391
+ calculateRange = memo(
1392
+ () => [
1393
+ this.getMeasurements(),
1394
+ this.getSize(),
1395
+ this.getScrollOffset(),
1396
+ this.options.lanes,
1397
+ ],
1398
+ (measurements, outerSize, scrollOffset, lanes) => {
1399
+ if (measurements.length === 0 || outerSize === 0) {
1400
+ this.range = null
1401
+ return null
1402
+ }
1403
+ this.range = calculateRangeImpl(
1404
+ measurements,
1405
+ outerSize,
1406
+ scrollOffset,
1407
+ lanes,
1408
+ // Pass the typed array so binary search + forward-walk can read
1409
+ // start/end directly from Float64Array, skipping the Proxy traps.
1410
+ lanes === 1 && this._flatMeasurements != null
1411
+ ? this._flatMeasurements
1412
+ : null,
1413
+ )
1414
+ return this.range
1415
+ },
1416
+ {
1417
+ key: process.env.NODE_ENV !== 'production' && 'calculateRange',
1418
+ debug: () => this.options.debug,
1419
+ },
1420
+ )
1421
+
1422
+ getVirtualIndexes = memo(
1423
+ () => {
1424
+ let startIndex: number | null = null
1425
+ let endIndex: number | null = null
1426
+ const range = this.calculateRange()
1427
+ if (range) {
1428
+ startIndex = range.startIndex
1429
+ endIndex = range.endIndex
1430
+ }
1431
+ this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex])
1432
+ return [
1433
+ this.options.rangeExtractor,
1434
+ this.options.overscan,
1435
+ this.options.count,
1436
+ startIndex,
1437
+ endIndex,
1438
+ ]
1439
+ },
1440
+ (rangeExtractor, overscan, count, startIndex, endIndex) => {
1441
+ return startIndex === null || endIndex === null
1442
+ ? []
1443
+ : rangeExtractor({
1444
+ startIndex,
1445
+ endIndex,
1446
+ overscan,
1447
+ count,
1448
+ })
1449
+ },
1450
+ {
1451
+ key: process.env.NODE_ENV !== 'production' && 'getVirtualIndexes',
1452
+ debug: () => this.options.debug,
1453
+ },
1454
+ )
1455
+
1456
+ indexFromElement = (node: TItemElement) => {
1457
+ const attributeName = this.options.indexAttribute
1458
+ const indexStr = node.getAttribute(attributeName)
1459
+
1460
+ if (!indexStr) {
1461
+ console.warn(
1462
+ `Missing attribute name '${attributeName}={index}' on measured element.`,
1463
+ )
1464
+ return -1
1465
+ }
1466
+
1467
+ return parseInt(indexStr, 10)
1468
+ }
1469
+
1470
+ /**
1471
+ * Determines if an item at the given index should be measured during smooth scroll.
1472
+ * During smooth scroll, only items within a buffer range around the target are measured
1473
+ * to prevent items far from the target from pushing it away.
1474
+ */
1475
+ private shouldMeasureDuringScroll = (index: number): boolean => {
1476
+ // No scroll state or not smooth scroll - always allow measurements
1477
+ if (!this.scrollState || this.scrollState.behavior !== 'smooth') {
1478
+ return true
1479
+ }
1480
+
1481
+ const scrollIndex =
1482
+ this.scrollState.index ??
1483
+ this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)?.index
1484
+
1485
+ if (scrollIndex !== undefined && this.range) {
1486
+ // Allow measurements within a buffer range around the scroll target
1487
+ const bufferSize = Math.max(
1488
+ this.options.overscan,
1489
+ Math.ceil((this.range.endIndex - this.range.startIndex) / 2),
1490
+ )
1491
+ const minIndex = Math.max(0, scrollIndex - bufferSize)
1492
+ const maxIndex = Math.min(
1493
+ this.options.count - 1,
1494
+ scrollIndex + bufferSize,
1495
+ )
1496
+ return index >= minIndex && index <= maxIndex
1497
+ }
1498
+
1499
+ return true
1500
+ }
1501
+
1502
+ measureElement = (node: TItemElement | null) => {
1503
+ if (!node) {
1504
+ this.elementsCache.forEach((cached, key) => {
1505
+ if (!cached.isConnected) {
1506
+ this.observer.unobserve(cached)
1507
+ this.elementsCache.delete(key)
1508
+ }
1509
+ })
1510
+ return
1511
+ }
1512
+
1513
+ const index = this.indexFromElement(node)
1514
+ const key = this.options.getItemKey(index)
1515
+ const prevNode = this.elementsCache.get(key)
1516
+
1517
+ if (prevNode !== node) {
1518
+ if (prevNode) {
1519
+ this.observer.unobserve(prevNode)
1520
+ }
1521
+ this.observer.observe(node)
1522
+ this.elementsCache.set(key, node)
1523
+ }
1524
+
1525
+ // Sync-measure when idle (initial render) or during programmatic scrolling
1526
+ // (scrollToIndex/scrollToOffset) where reconcileScroll needs sizes in the same frame.
1527
+ // During normal user scrolling, skip sync measurement — the RO callback handles it async.
1528
+ if (
1529
+ (!this.isScrolling || this.scrollState) &&
1530
+ this.shouldMeasureDuringScroll(index)
1531
+ ) {
1532
+ this.resizeItem(index, this.options.measureElement(node, undefined, this))
1533
+ }
1534
+ }
1535
+
1536
+ resizeItem = (index: number, size: number) => {
1537
+ if (index < 0 || index >= this.options.count) return
1538
+
1539
+ // Fast field reads. For lanes===1 we read raw start/size from the flat
1540
+ // typed array, avoiding a Proxy.get + VirtualItem allocation per call.
1541
+ // For lanes>1 we fall back to the cached VirtualItem array.
1542
+ let cachedSize: number
1543
+ let itemStart: number
1544
+ let key: Key
1545
+ const flat = this._flatMeasurements
1546
+ if (this.options.lanes === 1 && flat !== null) {
1547
+ key = this.options.getItemKey(index)
1548
+ itemStart = flat[index * 2]!
1549
+ cachedSize = flat[index * 2 + 1]!
1550
+ } else {
1551
+ const item = this.measurementsCache[index]
1552
+ if (!item) return
1553
+ key = item.key
1554
+ itemStart = item.start
1555
+ cachedSize = item.size
1556
+ }
1557
+
1558
+ const itemSize = this.itemSizeCache.get(key) ?? cachedSize
1559
+ const delta = size - itemSize
1560
+
1561
+ if (delta !== 0) {
1562
+ const wasAtEnd =
1563
+ this.options.anchorTo === 'end' &&
1564
+ this.scrollState?.behavior !== 'smooth' &&
1565
+ this.getVirtualDistanceFromEnd() <= this.options.scrollEndThreshold
1566
+ const prevTotalSize = wasAtEnd ? this.getTotalSize() : 0
1567
+ // Default anchoring predicate (used unless the consumer supplies a
1568
+ // custom shouldAdjustScrollPositionOnItemSizeChange).
1569
+ const scrollOffsetWithAdj =
1570
+ this.getScrollOffset() + this.scrollAdjustments
1571
+ const isFirstMeasure = !this.itemSizeCache.has(key)
1572
+ const defaultShouldAdjust = isFirstMeasure
1573
+ ? // First measurement: compensate any item whose top sits above the
1574
+ // fold — the estimate→actual delta must be corrected regardless of
1575
+ // scroll direction, since the whole estimated block was above it.
1576
+ itemStart < scrollOffsetWithAdj
1577
+ : // Re-measurement: only compensate an item that is ENTIRELY above the
1578
+ // fold. An item that merely *spans* the fold (top above, bottom
1579
+ // below — e.g. a streaming chat message growing at its bottom)
1580
+ // changes size *below* the anchor point, so shifting scrollTop by the
1581
+ // delta would drag the viewport downward on every growth (#1218).
1582
+ // Also skip during backward scroll to avoid the "items jump while
1583
+ // scrolling up" cascade.
1584
+ itemStart + itemSize <= scrollOffsetWithAdj &&
1585
+ this.scrollDirection !== 'backward'
1586
+ const shouldAdjustScroll =
1587
+ this.scrollState?.behavior !== 'smooth' &&
1588
+ (this.shouldAdjustScrollPositionOnItemSizeChange !== undefined
1589
+ ? this.shouldAdjustScrollPositionOnItemSizeChange(
1590
+ // The callback expects a VirtualItem; build one lazily only
1591
+ // when the consumer actually supplied a custom predicate.
1592
+ this.measurementsCache[index] ?? {
1593
+ index,
1594
+ key,
1595
+ start: itemStart,
1596
+ size: cachedSize,
1597
+ end: itemStart + cachedSize,
1598
+ lane: 0,
1599
+ },
1600
+ delta,
1601
+ this,
1602
+ )
1603
+ : defaultShouldAdjust)
1604
+
1605
+ if (this.pendingMin === null || index < this.pendingMin) {
1606
+ this.pendingMin = index
1607
+ }
1608
+ this.itemSizeCache.set(key, size)
1609
+ this.itemSizeCacheVersion++
1610
+
1611
+ let adjustedSync = false
1612
+ if (wasAtEnd) {
1613
+ adjustedSync = this.applyScrollAdjustment(
1614
+ this.getTotalSize() - prevTotalSize,
1615
+ )
1616
+ } else if (shouldAdjustScroll) {
1617
+ adjustedSync = this.applyScrollAdjustment(delta)
1618
+ }
1619
+
1620
+ // When we just moved `scrollTop` to compensate for an above-viewport
1621
+ // resize, the grown item transforms must commit in the SAME frame as
1622
+ // that write. `applyScrollAdjustment` writes `scrollTop` synchronously
1623
+ // inside this ResizeObserver callback, but an async `notify` schedules
1624
+ // the transform render for a later commit — so the browser can paint
1625
+ // one frame with the new `scrollTop` and the old positions, and the
1626
+ // viewport visibly jumps by `delta` before snapping back (#1227). A
1627
+ // synchronous notify flushes the render in this same callback, so both
1628
+ // land in one paint. When nothing moved (or the write was deferred on
1629
+ // iOS), keep the cheaper async notify.
1630
+ this.notify(adjustedSync)
1631
+ }
1632
+ }
1633
+
1634
+ getVirtualItems = memo(
1635
+ () => [this.getVirtualIndexes(), this.getMeasurements()],
1636
+ (indexes, measurements) => {
1637
+ const virtualItems: Array<VirtualItem> = []
1638
+
1639
+ for (let k = 0, len = indexes.length; k < len; k++) {
1640
+ const i = indexes[k]!
1641
+ const measurement = measurements[i]!
1642
+
1643
+ virtualItems.push(measurement)
1644
+ }
1645
+
1646
+ return virtualItems
1647
+ },
1648
+ {
1649
+ key: process.env.NODE_ENV !== 'production' && 'getVirtualItems',
1650
+ debug: () => this.options.debug,
1651
+ },
1652
+ )
1653
+
1654
+ getVirtualItemForOffset = (offset: number) => {
1655
+ const measurements = this.getMeasurements()
1656
+ if (measurements.length === 0) {
1657
+ return undefined
1658
+ }
1659
+ // Same fast-path as calculateRange: read start values directly from the
1660
+ // typed array during binary search to skip the Proxy.get materialization
1661
+ // per probe.
1662
+ const flat = this._flatMeasurements
1663
+ const useFlat = this.options.lanes === 1 && flat != null
1664
+ const idx = findNearestBinarySearch(
1665
+ 0,
1666
+ measurements.length - 1,
1667
+ useFlat
1668
+ ? (i: number) => flat[i * 2]!
1669
+ : (i: number) => notUndefined(measurements[i]).start,
1670
+ offset,
1671
+ )
1672
+ return notUndefined(measurements[idx])
1673
+ }
1674
+
1675
+ private getMaxScrollOffset = () => {
1676
+ if (!this.scrollElement) return 0
1677
+
1678
+ if ('scrollHeight' in this.scrollElement) {
1679
+ // Element
1680
+ return this.options.horizontal
1681
+ ? this.scrollElement.scrollWidth - this.scrollElement.clientWidth
1682
+ : this.scrollElement.scrollHeight - this.scrollElement.clientHeight
1683
+ } else {
1684
+ // Window
1685
+ const doc = this.scrollElement.document.documentElement
1686
+ return this.options.horizontal
1687
+ ? doc.scrollWidth - this.scrollElement.innerWidth
1688
+ : doc.scrollHeight - this.scrollElement.innerHeight
1689
+ }
1690
+ }
1691
+
1692
+ private getVirtualDistanceFromEnd = () => {
1693
+ return Math.max(
1694
+ this.getTotalSize() - this.getSize() - this.getScrollOffset(),
1695
+ 0,
1696
+ )
1697
+ }
1698
+
1699
+ getDistanceFromEnd = () => {
1700
+ return Math.max(this.getMaxScrollOffset() - this.getScrollOffset(), 0)
1701
+ }
1702
+
1703
+ isAtEnd = (threshold = this.options.scrollEndThreshold) => {
1704
+ return this.getDistanceFromEnd() <= threshold
1705
+ }
1706
+
1707
+ getOffsetForAlignment = (
1708
+ toOffset: number,
1709
+ align: ScrollAlignment,
1710
+ itemSize = 0,
1711
+ ) => {
1712
+ if (!this.scrollElement) return 0
1713
+
1714
+ const size = this.getSize()
1715
+ const scrollOffset = this.getScrollOffset()
1716
+
1717
+ if (align === 'auto') {
1718
+ align = toOffset >= scrollOffset + size ? 'end' : 'start'
1719
+ }
1720
+
1721
+ if (align === 'center') {
1722
+ // When aligning to a particular item (e.g. with scrollToIndex),
1723
+ // adjust offset by the size of the item to center on the item
1724
+ toOffset += (itemSize - size) / 2
1725
+ } else if (align === 'end') {
1726
+ toOffset -= size
1727
+ }
1728
+
1729
+ const maxOffset = this.getMaxScrollOffset()
1730
+
1731
+ return Math.max(Math.min(maxOffset, toOffset), 0)
1732
+ }
1733
+
1734
+ getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {
1735
+ index = Math.max(0, Math.min(index, this.options.count - 1))
1736
+
1737
+ const size = this.getSize()
1738
+ const scrollOffset = this.getScrollOffset()
1739
+
1740
+ const item = this.measurementsCache[index]
1741
+ if (!item) return
1742
+
1743
+ if (align === 'auto') {
1744
+ if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {
1745
+ align = 'end'
1746
+ } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {
1747
+ align = 'start'
1748
+ } else {
1749
+ return [scrollOffset, align] as const
1750
+ }
1751
+ }
1752
+
1753
+ // For the last item with 'end' alignment, use browser's actual max scroll
1754
+ // to account for borders/padding that aren't in our measurements
1755
+ if (align === 'end' && index === this.options.count - 1) {
1756
+ return [this.getMaxScrollOffset(), align] as const
1757
+ }
1758
+
1759
+ const toOffset =
1760
+ align === 'end'
1761
+ ? item.end + this.options.scrollPaddingEnd
1762
+ : item.start - this.options.scrollPaddingStart
1763
+
1764
+ return [
1765
+ this.getOffsetForAlignment(toOffset, align, item.size),
1766
+ align,
1767
+ ] as const
1768
+ }
1769
+
1770
+ scrollToOffset = (
1771
+ toOffset: number,
1772
+ { align = 'start', behavior = 'auto' }: ScrollToOffsetOptions = {},
1773
+ ) => {
1774
+ // An absolute scroll command derives its target from current
1775
+ // measurements, so any iOS-deferred compensation still pending is stale by
1776
+ // definition — the command already accounts for the measurements the delta
1777
+ // was compensating for. Drop it so _flushIosDeferredIfReady doesn't replay
1778
+ // it onto the just-established position (relative commands like scrollBy
1779
+ // intentionally keep the deferral, since they build on the current offset).
1780
+ this._iosDeferredAdjustment = 0
1781
+
1782
+ const offset = this.getOffsetForAlignment(toOffset, align)
1783
+
1784
+ const now = this.now()
1785
+ this.scrollState = {
1786
+ index: null,
1787
+ align,
1788
+ behavior,
1789
+ startedAt: now,
1790
+ lastTargetOffset: offset,
1791
+ stableFrames: 0,
1792
+ }
1793
+
1794
+ this._scrollToOffset(offset, { adjustments: undefined, behavior })
1795
+
1796
+ this.scheduleScrollReconcile()
1797
+ }
1798
+
1799
+ scrollToIndex = (
1800
+ index: number,
1801
+ {
1802
+ align: initialAlign = 'auto',
1803
+ behavior = 'auto',
1804
+ }: ScrollToIndexOptions = {},
1805
+ ) => {
1806
+ // See scrollToOffset: an absolute target invalidates any pending
1807
+ // iOS-deferred compensation.
1808
+ this._iosDeferredAdjustment = 0
1809
+
1810
+ index = Math.max(0, Math.min(index, this.options.count - 1))
1811
+
1812
+ const offsetInfo = this.getOffsetForIndex(index, initialAlign)
1813
+ if (!offsetInfo) {
1814
+ return
1815
+ }
1816
+ const [offset, align] = offsetInfo
1817
+
1818
+ const now = this.now()
1819
+ this.scrollState = {
1820
+ index,
1821
+ align,
1822
+ behavior,
1823
+ startedAt: now,
1824
+ lastTargetOffset: offset,
1825
+ stableFrames: 0,
1826
+ }
1827
+
1828
+ this._scrollToOffset(offset, { adjustments: undefined, behavior })
1829
+
1830
+ this.scheduleScrollReconcile()
1831
+ }
1832
+
1833
+ scrollBy = (
1834
+ delta: number,
1835
+ { behavior = 'auto' }: ScrollToOffsetOptions = {},
1836
+ ) => {
1837
+ const offset = this.getScrollOffset() + delta
1838
+ const now = this.now()
1839
+
1840
+ this.scrollState = {
1841
+ index: null,
1842
+ align: 'start',
1843
+ behavior,
1844
+ startedAt: now,
1845
+ lastTargetOffset: offset,
1846
+ stableFrames: 0,
1847
+ }
1848
+
1849
+ this._scrollToOffset(offset, { adjustments: undefined, behavior })
1850
+
1851
+ this.scheduleScrollReconcile()
1852
+ }
1853
+
1854
+ scrollToEnd = ({ behavior = 'auto' }: ScrollToEndOptions = {}) => {
1855
+ if (this.options.count > 0) {
1856
+ this.scrollToIndex(this.options.count - 1, {
1857
+ align: 'end',
1858
+ behavior,
1859
+ })
1860
+ return
1861
+ }
1862
+
1863
+ this.scrollToOffset(Math.max(this.getTotalSize() - this.getSize(), 0), {
1864
+ behavior,
1865
+ })
1866
+ }
1867
+
1868
+ getTotalSize = () => {
1869
+ const measurements = this.getMeasurements()
1870
+
1871
+ let end: number
1872
+ // If there are no measurements, set the end to paddingStart
1873
+ // If there is only one lane, use the last measurement's end
1874
+ // Otherwise find the maximum end value among all measurements
1875
+ if (measurements.length === 0) {
1876
+ end = this.options.paddingStart
1877
+ } else if (this.options.lanes === 1) {
1878
+ // Fast path: read last item's end directly from the flat typed array
1879
+ // when available; avoids a Proxy.get + VirtualItem materialization
1880
+ // just to call getTotalSize (which React renders trigger every commit).
1881
+ const lastIdx = measurements.length - 1
1882
+ const flat = this._flatMeasurements
1883
+ if (flat != null) {
1884
+ end = flat[lastIdx * 2]! + flat[lastIdx * 2 + 1]!
1885
+ } else {
1886
+ end = measurements[lastIdx]?.end ?? 0
1887
+ }
1888
+ } else {
1889
+ const endByLane = Array<number | null>(this.options.lanes).fill(null)
1890
+ let endIndex = measurements.length - 1
1891
+ while (endIndex >= 0 && endByLane.some((val) => val === null)) {
1892
+ const item = measurements[endIndex]!
1893
+ if (endByLane[item.lane] === null) {
1894
+ endByLane[item.lane] = item.end
1895
+ }
1896
+
1897
+ endIndex--
1898
+ }
1899
+
1900
+ end = Math.max(...endByLane.filter((val): val is number => val !== null))
1901
+ }
1902
+
1903
+ return Math.max(
1904
+ end - this.options.scrollMargin + this.options.paddingEnd,
1905
+ 0,
1906
+ )
1907
+ }
1908
+
1909
+ /**
1910
+ * Returns a snapshot of currently-measured items suitable for round-
1911
+ * tripping through state storage (sessionStorage, history, etc.) and
1912
+ * passing back as `initialMeasurementsCache` on remount. Pair with the
1913
+ * current `scrollOffset` to restore exact scroll position after navigation.
1914
+ *
1915
+ * Only items the consumer has actually rendered (and thus measured) appear
1916
+ * in the snapshot; unmeasured items will fall back to `estimateSize` on
1917
+ * restore. Returns an empty array if no items have been measured.
1918
+ */
1919
+ takeSnapshot = (): Array<VirtualItem> => {
1920
+ const snapshot: Array<VirtualItem> = []
1921
+ if (this.itemSizeCache.size === 0) return snapshot
1922
+ // Iterate measurementsCache only for indices whose key is in itemSizeCache
1923
+ // (i.e., have been measured). We build VirtualItem objects with the
1924
+ // current start/size/end so they can be persisted as plain data.
1925
+ const m = this.getMeasurements()
1926
+ for (const item of m) {
1927
+ if (item && this.itemSizeCache.has(item.key)) {
1928
+ // Force materialization (lazy path) and copy plain fields.
1929
+ snapshot.push({
1930
+ index: item.index,
1931
+ key: item.key,
1932
+ start: item.start,
1933
+ size: item.size,
1934
+ end: item.end,
1935
+ lane: item.lane,
1936
+ })
1937
+ }
1938
+ }
1939
+ return snapshot
1940
+ }
1941
+
1942
+ private _scrollToOffset = (
1943
+ offset: number,
1944
+ {
1945
+ adjustments,
1946
+ behavior,
1947
+ }: {
1948
+ adjustments: number | undefined
1949
+ behavior: ScrollBehavior | undefined
1950
+ },
1951
+ ) => {
1952
+ // Record the intended logical scroll target so the next scroll event
1953
+ // can reconcile against subpixel rounding by the browser.
1954
+ this._intendedScrollOffset = offset + (adjustments ?? 0)
1955
+ this.options.scrollToFn(offset, { behavior, adjustments }, this)
1956
+ }
1957
+
1958
+ measure = () => {
1959
+ // Reset pendingMin so the next getMeasurements rebuilds from index 0.
1960
+ // Without this, a prior resizeItem() that left pendingMin > 0 would
1961
+ // cause the rebuild to preserve stale items before that index.
1962
+ this.pendingMin = null
1963
+ this.itemSizeCache.clear()
1964
+ this.laneAssignments.clear() // Clear lane cache for full re-layout
1965
+ this.itemSizeCacheVersion++
1966
+ this.notify(false)
1967
+ }
1968
+ }
1969
+
1970
+ const findNearestBinarySearch = (
1971
+ low: number,
1972
+ high: number,
1973
+ getCurrentValue: (i: number) => number,
1974
+ value: number,
1975
+ ) => {
1976
+ while (low <= high) {
1977
+ const middle = ((low + high) / 2) | 0
1978
+ const currentValue = getCurrentValue(middle)
1979
+
1980
+ if (currentValue < value) {
1981
+ low = middle + 1
1982
+ } else if (currentValue > value) {
1983
+ high = middle - 1
1984
+ } else {
1985
+ return middle
1986
+ }
1987
+ }
1988
+
1989
+ if (low > 0) {
1990
+ return low - 1
1991
+ } else {
1992
+ return 0
1993
+ }
1994
+ }
1995
+
1996
+ // Monomorphic Float64Array variant — reads start values directly at stride
1997
+ // 2 instead of through a getter closure. JITs the inner load to a typed-
1998
+ // array bounds-check + load with no indirect call.
1999
+ function findNearestBinarySearchFlat(
2000
+ flat: Float64Array,
2001
+ high: number,
2002
+ value: number,
2003
+ ) {
2004
+ let low = 0
2005
+ while (low <= high) {
2006
+ const middle = ((low + high) / 2) | 0
2007
+ const currentValue = flat[middle * 2]!
2008
+
2009
+ if (currentValue < value) {
2010
+ low = middle + 1
2011
+ } else if (currentValue > value) {
2012
+ high = middle - 1
2013
+ } else {
2014
+ return middle
2015
+ }
2016
+ }
2017
+ return low > 0 ? low - 1 : 0
2018
+ }
2019
+
2020
+ function calculateRangeImpl(
2021
+ measurements: Array<VirtualItem>,
2022
+ outerSize: number,
2023
+ scrollOffset: number,
2024
+ lanes: number,
2025
+ flat: Float64Array | null,
2026
+ ) {
2027
+ const lastIndex = measurements.length - 1
2028
+
2029
+ // handle case when item count is less than or equal to lanes
2030
+ if (measurements.length <= lanes) {
2031
+ return { startIndex: 0, endIndex: lastIndex }
2032
+ }
2033
+
2034
+ if (lanes === 1 && flat !== null) {
2035
+ // Hot single-lane path: typed-array reads, no closures, no Proxy traps.
2036
+ const startIndex = findNearestBinarySearchFlat(
2037
+ flat,
2038
+ lastIndex,
2039
+ scrollOffset,
2040
+ )
2041
+ let endIndex = startIndex
2042
+ const limit = scrollOffset + outerSize
2043
+ while (
2044
+ endIndex < lastIndex &&
2045
+ flat[endIndex * 2]! + flat[endIndex * 2 + 1]! < limit
2046
+ ) {
2047
+ endIndex++
2048
+ }
2049
+ return { startIndex, endIndex }
2050
+ }
2051
+
2052
+ // Fallback (lanes > 1 or no flat array): closure-based reads.
2053
+ const getStart = (index: number) => measurements[index]!.start
2054
+ let startIndex = findNearestBinarySearch(0, lastIndex, getStart, scrollOffset)
2055
+ let endIndex = startIndex
2056
+
2057
+ if (lanes === 1) {
2058
+ while (
2059
+ endIndex < lastIndex &&
2060
+ measurements[endIndex]!.end < scrollOffset + outerSize
2061
+ ) {
2062
+ endIndex++
2063
+ }
2064
+ } else if (lanes > 1) {
2065
+ // Expand forward until we include the visible items from all lanes
2066
+ // which are closer to the end of the virtualizer window
2067
+ const endPerLane = Array(lanes).fill(0)
2068
+ while (
2069
+ endIndex < lastIndex &&
2070
+ endPerLane.some((pos) => pos < scrollOffset + outerSize)
2071
+ ) {
2072
+ const item = measurements[endIndex]!
2073
+ endPerLane[item.lane] = item.end
2074
+ endIndex++
2075
+ }
2076
+
2077
+ // Expand backward until we include all lanes' visible items
2078
+ // closer to the top
2079
+ const startPerLane = Array(lanes).fill(scrollOffset + outerSize)
2080
+ while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {
2081
+ const item = measurements[startIndex]!
2082
+ startPerLane[item.lane] = item.start
2083
+ startIndex--
2084
+ }
2085
+
2086
+ // Align startIndex to the beginning of its lane
2087
+ startIndex = Math.max(0, startIndex - (startIndex % lanes))
2088
+ // Align endIndex to the end of its lane
2089
+ endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - (endIndex % lanes)))
2090
+ }
2091
+
2092
+ return { startIndex, endIndex }
2093
+ }
node_modules/@tanstack/virtual-core/src/lazy-measurements.ts ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Lazy materialization for the lanes===1 fast path. Backed by a
2
+ // Float64Array (stride 2: start, size, …); VirtualItems are constructed on
3
+ // first indexed read and cached. Saves the per-item object allocation at
4
+ // large list counts where most items are never visible.
5
+
6
+ import type { VirtualItem } from './index'
7
+
8
+ type Key = number | string | bigint
9
+
10
+ export function createLazyMeasurementsView(
11
+ count: number,
12
+ flat: Float64Array,
13
+ getItemKey: (i: number) => Key,
14
+ ): Array<VirtualItem> {
15
+ const cache: Array<VirtualItem | undefined> = new Array(count)
16
+ return new Proxy(cache as any, {
17
+ get(target, prop, receiver) {
18
+ if (typeof prop === 'string') {
19
+ // Cheap digit-prefix sniff before number coerce.
20
+ const c = prop.charCodeAt(0)
21
+ if (c >= 48 && c <= 57) {
22
+ const i = +prop
23
+ if (Number.isInteger(i) && i >= 0 && i < count) {
24
+ let v = target[i]
25
+ if (!v) {
26
+ const s = flat[i * 2]!
27
+ v = target[i] = {
28
+ index: i,
29
+ key: getItemKey(i),
30
+ start: s,
31
+ size: flat[i * 2 + 1]!,
32
+ end: s + flat[i * 2 + 1]!,
33
+ lane: 0,
34
+ }
35
+ }
36
+ return v
37
+ }
38
+ }
39
+ if (prop === 'length') return count
40
+ }
41
+ return Reflect.get(target, prop, receiver)
42
+ },
43
+ }) as Array<VirtualItem>
44
+ }
node_modules/@tanstack/virtual-core/src/utils.ts ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export type NoInfer<A extends any> = [A][A extends any ? 0 : never]
2
+
3
+ export type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
4
+
5
+ export function memo<TDeps extends ReadonlyArray<any>, TResult>(
6
+ getDeps: () => [...TDeps],
7
+ fn: (...args: NoInfer<[...TDeps]>) => TResult,
8
+ opts: {
9
+ key: false | string
10
+ debug?: () => boolean
11
+ onChange?: (result: TResult) => void
12
+ initialDeps?: TDeps
13
+ skipInitialOnChange?: boolean
14
+ },
15
+ ) {
16
+ let deps = opts.initialDeps ?? []
17
+ let result: TResult | undefined
18
+ let isInitial = true
19
+
20
+ function memoizedFunction(): TResult {
21
+ // Debug-only timing. In production builds, `process.env.NODE_ENV !==
22
+ // 'production'` is constant-folded to `false` by downstream minifiers
23
+ // (Terser/esbuild/swc with `define`), which DCEs the entire block.
24
+ const debugEnabled =
25
+ process.env.NODE_ENV !== 'production' && !!opts.key && !!opts.debug?.()
26
+ let depTime = 0
27
+ if (debugEnabled) depTime = Date.now()
28
+
29
+ const newDeps = getDeps()
30
+
31
+ const depsChanged =
32
+ newDeps.length !== deps.length ||
33
+ newDeps.some((dep: any, index: number) => deps[index] !== dep)
34
+
35
+ if (!depsChanged) {
36
+ return result!
37
+ }
38
+
39
+ deps = newDeps
40
+
41
+ let resultTime = 0
42
+ if (debugEnabled) resultTime = Date.now()
43
+
44
+ result = fn(...newDeps)
45
+
46
+ if (debugEnabled) {
47
+ const depEndTime = Math.round((Date.now() - depTime) * 100) / 100
48
+ const resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100
49
+ const resultFpsPercentage = resultEndTime / 16
50
+
51
+ const pad = (str: number | string, num: number) => {
52
+ str = String(str)
53
+ while (str.length < num) {
54
+ str = ' ' + str
55
+ }
56
+ return str
57
+ }
58
+
59
+ console.info(
60
+ `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,
61
+ `
62
+ font-size: .6rem;
63
+ font-weight: bold;
64
+ color: hsl(${Math.max(
65
+ 0,
66
+ Math.min(120 - 120 * resultFpsPercentage, 120),
67
+ )}deg 100% 31%);`,
68
+ opts?.key,
69
+ )
70
+ }
71
+
72
+ if (opts?.onChange && !(isInitial && opts.skipInitialOnChange)) {
73
+ opts.onChange(result)
74
+ }
75
+
76
+ isInitial = false
77
+
78
+ return result
79
+ }
80
+
81
+ // Attach updateDeps to the function itself
82
+ memoizedFunction.updateDeps = (newDeps: [...TDeps]) => {
83
+ deps = newDeps
84
+ }
85
+
86
+ return memoizedFunction
87
+ }
88
+
89
+ export function notUndefined<T>(value: T | undefined, msg?: string): T {
90
+ if (value === undefined) {
91
+ throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)
92
+ } else {
93
+ return value
94
+ }
95
+ }
96
+
97
+ export const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1.01
98
+
99
+ export const debounce = (
100
+ targetWindow: Window & typeof globalThis,
101
+ fn: Function,
102
+ ms: number,
103
+ ) => {
104
+ let timeoutId: number
105
+ return function (this: any, ...args: Array<any>) {
106
+ targetWindow.clearTimeout(timeoutId)
107
+ timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms)
108
+ }
109
+ }
node_modules/@testing-library/dom/LICENSE ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+ Copyright (c) 2017 Kent C. Dodds
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
node_modules/@testing-library/dom/README.md ADDED
@@ -0,0 +1,402 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+ <h1>DOM Testing Library</h1>
3
+
4
+ <a href="https://www.emojione.com/emoji/1f419">
5
+ <img
6
+ height="80"
7
+ width="80"
8
+ alt="octopus"
9
+ src="https://raw.githubusercontent.com/testing-library/dom-testing-library/main/other/octopus.png"
10
+ />
11
+ </a>
12
+
13
+ <p>Simple and complete DOM testing utilities that encourage good testing
14
+ practices.</p>
15
+
16
+ [**Read the docs**](https://testing-library.com/dom) |
17
+ [Edit the docs](https://github.com/testing-library/testing-library-docs)
18
+
19
+ </div>
20
+
21
+ <hr />
22
+
23
+ <!-- prettier-ignore-start -->
24
+ [![Build Status][build-badge]][build]
25
+ [![Code Coverage][coverage-badge]][coverage]
26
+ [![version][version-badge]][package]
27
+ [![downloads][downloads-badge]][npmtrends]
28
+ [![MIT License][license-badge]][license]
29
+ [![All Contributors][all-contributors-badge]](#contributors)
30
+ [![PRs Welcome][prs-badge]][prs]
31
+ [![Code of Conduct][coc-badge]][coc]
32
+ [![Discord][discord-badge]][discord]
33
+
34
+ [![Watch on GitHub][github-watch-badge]][github-watch]
35
+ [![Star on GitHub][github-star-badge]][github-star]
36
+ [![Tweet][twitter-badge]][twitter]
37
+ <!-- prettier-ignore-end -->
38
+
39
+ <div align="center">
40
+ <a href="https://testingjavascript.com">
41
+ <img
42
+ width="500"
43
+ alt="TestingJavaScript.com Learn the smart, efficient way to test any JavaScript application."
44
+ src="https://raw.githubusercontent.com/testing-library/dom-testing-library/main/other/testingjavascript.jpg"
45
+ />
46
+ </a>
47
+ </div>
48
+
49
+ ## Table of Contents
50
+
51
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
52
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
53
+
54
+ - [The Problem](#the-problem)
55
+ - [This Solution](#this-solution)
56
+ - [Installation](#installation)
57
+ - [Documentation](#documentation)
58
+ - [Guiding Principles](#guiding-principles)
59
+ - [Contributors](#contributors)
60
+ - [LICENSE](#license)
61
+
62
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
63
+
64
+ ## The Problem
65
+
66
+ You want to write maintainable tests for your Web UI. As a part of this goal,
67
+ you want your tests to avoid including implementation details of your components
68
+ and rather focus on making your tests give you the confidence for which they are
69
+ intended. As part of this, you want your testbase to be maintainable in the long
70
+ run so refactors of your components (changes to implementation but not
71
+ functionality) don't break your tests and slow you and your team down.
72
+
73
+ ## This Solution
74
+
75
+ The `DOM Testing Library` is a very light-weight solution for testing DOM nodes
76
+ (whether simulated with [`JSDOM`](https://github.com/jsdom/jsdom) as provided by
77
+ default with [Jest][] or in the browser). The main utilities it provides involve
78
+ querying the DOM for nodes in a way that's similar to how the user finds
79
+ elements on the page. In this way, the library helps ensure your tests give you
80
+ confidence in your UI code. The `DOM Testing Library`'s primary guiding
81
+ principle is:
82
+
83
+ > [The more your tests resemble the way your software is used, the more
84
+ > confidence they can give you.][guiding-principle]
85
+
86
+ ## Installation
87
+
88
+ This module is distributed via [npm][npm] which is bundled with [node][node] and
89
+ should be installed as one of your project's `devDependencies`:
90
+
91
+ ```
92
+ npm install --save-dev @testing-library/dom
93
+ ```
94
+
95
+ > [**Docs**](https://testing-library.com/docs/install)
96
+
97
+ ## Documentation
98
+
99
+ Read the docs (and discover framework and tool-specific implementations) at
100
+ [testing-library.com](https://testing-library.com/dom)
101
+
102
+ ## Guiding Principles
103
+
104
+ > [The more your tests resemble the way your software is used, the more
105
+ > confidence they can give you.][guiding-principle]
106
+
107
+ We try to only expose methods and utilities that encourage you to write tests
108
+ that closely resemble how your web pages are used.
109
+
110
+ Utilities are included in this project based on the following guiding
111
+ principles:
112
+
113
+ 1. If it relates to rendering components, it deals with DOM nodes rather than
114
+ component instances, nor should it encourage dealing with component
115
+ instances.
116
+ 2. It should be generally useful for testing the application components in the
117
+ way the user would use it. We _are_ making some trade-offs here because
118
+ we're using a computer and often a simulated browser environment, but in
119
+ general, utilities should encourage tests that use the components the way
120
+ they're intended to be used.
121
+ 3. Utility implementations and APIs should be simple and flexible.
122
+
123
+ At the end of the day, what we want is for this library to be pretty
124
+ light-weight, simple, and understandable.
125
+
126
+ ## Contributors
127
+
128
+ Thanks goes to these people ([emoji key][emojis]):
129
+
130
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
131
+ <!-- prettier-ignore-start -->
132
+ <!-- markdownlint-disable -->
133
+ <table>
134
+ <tbody>
135
+ <tr>
136
+ <td align="center" valign="top" width="14.28%"><a href="https://kentcdodds.com"><img src="https://avatars.githubusercontent.com/u/1500684?v=3?s=100" width="100px;" alt="Kent C. Dodds"/><br /><sub><b>Kent C. Dodds</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=kentcdodds" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=kentcdodds" title="Documentation">📖</a> <a href="#infra-kentcdodds" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=kentcdodds" title="Tests">⚠️</a></td>
137
+ <td align="center" valign="top" width="14.28%"><a href="https://argos-ci.com"><img src="https://avatars2.githubusercontent.com/u/266302?v=4?s=100" width="100px;" alt="Greg Bergé"/><br /><sub><b>Greg Bergé</b></sub></a><br /><a href="#ideas-neoziro" title="Ideas, Planning, & Feedback">🤔</a></td>
138
+ <td align="center" valign="top" width="14.28%"><a href="http://audiolion.github.io"><img src="https://avatars1.githubusercontent.com/u/2430381?v=4?s=100" width="100px;" alt="Ryan Castner"/><br /><sub><b>Ryan Castner</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=audiolion" title="Documentation">📖</a></td>
139
+ <td align="center" valign="top" width="14.28%"><a href="https://www.dnlsandiego.com"><img src="https://avatars0.githubusercontent.com/u/8008023?v=4?s=100" width="100px;" alt="Daniel Sandiego"/><br /><sub><b>Daniel Sandiego</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=dnlsandiego" title="Code">💻</a></td>
140
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Miklet"><img src="https://avatars2.githubusercontent.com/u/12592677?v=4?s=100" width="100px;" alt="Paweł Mikołajczyk"/><br /><sub><b>Paweł Mikołajczyk</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Miklet" title="Code">💻</a></td>
141
+ <td align="center" valign="top" width="14.28%"><a href="http://co.linkedin.com/in/alejandronanez/"><img src="https://avatars3.githubusercontent.com/u/464978?v=4?s=100" width="100px;" alt="Alejandro Ñáñez Ortiz"/><br /><sub><b>Alejandro Ñáñez Ortiz</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=alejandronanez" title="Documentation">📖</a></td>
142
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/pbomb"><img src="https://avatars0.githubusercontent.com/u/1402095?v=4?s=100" width="100px;" alt="Matt Parrish"/><br /><sub><b>Matt Parrish</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Apbomb" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=pbomb" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=pbomb" title="Documentation">📖</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=pbomb" title="Tests">⚠️</a></td>
143
+ </tr>
144
+ <tr>
145
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/wKovacs64"><img src="https://avatars1.githubusercontent.com/u/1288694?v=4?s=100" width="100px;" alt="Justin Hall"/><br /><sub><b>Justin Hall</b></sub></a><br /><a href="#platform-wKovacs64" title="Packaging/porting to new platform">📦</a></td>
146
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/antoaravinth"><img src="https://avatars1.githubusercontent.com/u/1241511?s=460&v=4?s=100" width="100px;" alt="Anto Aravinth"/><br /><sub><b>Anto Aravinth</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=antoaravinth" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=antoaravinth" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=antoaravinth" title="Documentation">📖</a></td>
147
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/JonahMoses"><img src="https://avatars2.githubusercontent.com/u/3462296?v=4?s=100" width="100px;" alt="Jonah Moses"/><br /><sub><b>Jonah Moses</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=JonahMoses" title="Documentation">📖</a></td>
148
+ <td align="center" valign="top" width="14.28%"><a href="http://team.thebrain.pro"><img src="https://avatars1.githubusercontent.com/u/4002543?v=4?s=100" width="100px;" alt="Łukasz Gandecki"/><br /><sub><b>Łukasz Gandecki</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=lgandecki" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=lgandecki" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=lgandecki" title="Documentation">📖</a></td>
149
+ <td align="center" valign="top" width="14.28%"><a href="https://sompylasar.github.io"><img src="https://avatars2.githubusercontent.com/u/498274?v=4?s=100" width="100px;" alt="Ivan Babak"/><br /><sub><b>Ivan Babak</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Asompylasar" title="Bug reports">🐛</a> <a href="#ideas-sompylasar" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=sompylasar" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=sompylasar" title="Documentation">📖</a></td>
150
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/jday3"><img src="https://avatars3.githubusercontent.com/u/4439618?v=4?s=100" width="100px;" alt="Jesse Day"/><br /><sub><b>Jesse Day</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jday3" title="Code">💻</a></td>
151
+ <td align="center" valign="top" width="14.28%"><a href="http://gnapse.github.io"><img src="https://avatars0.githubusercontent.com/u/15199?v=4?s=100" width="100px;" alt="Ernesto García"/><br /><sub><b>Ernesto García</b></sub></a><br /><a href="#question-gnapse" title="Answering Questions">💬</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=gnapse" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=gnapse" title="Documentation">📖</a></td>
152
+ </tr>
153
+ <tr>
154
+ <td align="center" valign="top" width="14.28%"><a href="http://jomaxx.com"><img src="https://avatars2.githubusercontent.com/u/2747424?v=4?s=100" width="100px;" alt="Josef Maxx Blake"/><br /><sub><b>Josef Maxx Blake</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jomaxx" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=jomaxx" title="Documentation">📖</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=jomaxx" title="Tests">⚠️</a></td>
155
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/alecook"><img src="https://avatars3.githubusercontent.com/u/725236?v=4?s=100" width="100px;" alt="Alex Cook"/><br /><sub><b>Alex Cook</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=alecook" title="Documentation">📖</a> <a href="#example-alecook" title="Examples">💡</a> <a href="https://github.com/testing-library/dom-testing-library/pulls?q=is%3Apr+reviewed-by%3Aalecook" title="Reviewed Pull Requests">👀</a></td>
156
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/dfcook"><img src="https://avatars3.githubusercontent.com/u/10348212?v=4?s=100" width="100px;" alt="Daniel Cook"/><br /><sub><b>Daniel Cook</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=dfcook" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=dfcook" title="Documentation">📖</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=dfcook" title="Tests">⚠️</a></td>
157
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/thchia"><img src="https://avatars2.githubusercontent.com/u/21194045?s=400&v=4?s=100" width="100px;" alt="Thomas Chia"/><br /><sub><b>Thomas Chia</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Athchia" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=thchia" title="Code">💻</a></td>
158
+ <td align="center" valign="top" width="14.28%"><a href="http://timdeschryver.dev"><img src="https://avatars.githubusercontent.com/u/28659384?v=4?s=100" width="100px;" alt="Tim Deschryver"/><br /><sub><b>Tim Deschryver</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=timdeschryver" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=timdeschryver" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/pulls?q=is%3Apr+reviewed-by%3Atimdeschryver" title="Reviewed Pull Requests">👀</a></td>
159
+ <td align="center" valign="top" width="14.28%"><a href="https://alexkrolick.com"><img src="https://avatars3.githubusercontent.com/u/1571667?v=4?s=100" width="100px;" alt="Alex Krolick"/><br /><sub><b>Alex Krolick</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=alexkrolick" title="Code">💻</a></td>
160
+ <td align="center" valign="top" width="14.28%"><a href="http://www.maddijoyce.com"><img src="https://avatars2.githubusercontent.com/u/2224291?v=4?s=100" width="100px;" alt="Maddi Joyce"/><br /><sub><b>Maddi Joyce</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=maddijoyce" title="Code">💻</a></td>
161
+ </tr>
162
+ <tr>
163
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/npeterkamps"><img src="https://avatars1.githubusercontent.com/u/25429764?v=4?s=100" width="100px;" alt="Peter Kamps"/><br /><sub><b>Peter Kamps</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Anpeterkamps" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=npeterkamps" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=npeterkamps" title="Tests">⚠️</a></td>
164
+ <td align="center" valign="top" width="14.28%"><a href="http://jonathanstoye.de"><img src="https://avatars2.githubusercontent.com/u/21689428?v=4?s=100" width="100px;" alt="Jonathan Stoye"/><br /><sub><b>Jonathan Stoye</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=JonathanStoye" title="Documentation">📖</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=JonathanStoye" title="Code">💻</a></td>
165
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/yongdamsh"><img src="https://avatars2.githubusercontent.com/u/4126644?v=4?s=100" width="100px;" alt="Sanghyeon Lee"/><br /><sub><b>Sanghyeon Lee</b></sub></a><br /><a href="#example-yongdamsh" title="Examples">💡</a></td>
166
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Dajust"><img src="https://avatars3.githubusercontent.com/u/8015514?v=4?s=100" width="100px;" alt="Justice Mba "/><br /><sub><b>Justice Mba </b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Dajust" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=Dajust" title="Documentation">📖</a> <a href="#ideas-Dajust" title="Ideas, Planning, & Feedback">🤔</a></td>
167
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/wgcrouch"><img src="https://avatars3.githubusercontent.com/u/340761?v=4?s=100" width="100px;" alt="Wayne Crouch"/><br /><sub><b>Wayne Crouch</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=wgcrouch" title="Code">💻</a></td>
168
+ <td align="center" valign="top" width="14.28%"><a href="http://benjaminelliott.co.uk"><img src="https://avatars1.githubusercontent.com/u/4996462?v=4?s=100" width="100px;" alt="Ben Elliott"/><br /><sub><b>Ben Elliott</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=benelliott" title="Code">💻</a></td>
169
+ <td align="center" valign="top" width="14.28%"><a href="http://nuances.co"><img src="https://avatars3.githubusercontent.com/u/577921?v=4?s=100" width="100px;" alt="Ruben Costa"/><br /><sub><b>Ruben Costa</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=rubencosta" title="Code">💻</a></td>
170
+ </tr>
171
+ <tr>
172
+ <td align="center" valign="top" width="14.28%"><a href="http://rbrtsmith.com/"><img src="https://avatars2.githubusercontent.com/u/4982001?v=4?s=100" width="100px;" alt="Robert Smith"/><br /><sub><b>Robert Smith</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Arbrtsmith" title="Bug reports">🐛</a> <a href="#ideas-rbrtsmith" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=rbrtsmith" title="Documentation">📖</a></td>
173
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/dadamssg"><img src="https://avatars3.githubusercontent.com/u/881986?v=4?s=100" width="100px;" alt="dadamssg"/><br /><sub><b>dadamssg</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=dadamssg" title="Code">💻</a></td>
174
+ <td align="center" valign="top" width="14.28%"><a href="https://neilkistner.com/"><img src="https://avatars1.githubusercontent.com/u/186971?v=4?s=100" width="100px;" alt="Neil Kistner"/><br /><sub><b>Neil Kistner</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=wyze" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=wyze" title="Tests">⚠️</a></td>
175
+ <td align="center" valign="top" width="14.28%"><a href="http://bdchauvette.net/"><img src="https://avatars3.githubusercontent.com/u/1448597?v=4?s=100" width="100px;" alt="Ben Chauvette"/><br /><sub><b>Ben Chauvette</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=bdchauvette" title="Code">💻</a></td>
176
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/JeffBaumgardt"><img src="https://avatars2.githubusercontent.com/u/777527?v=4?s=100" width="100px;" alt="Jeff Baumgardt"/><br /><sub><b>Jeff Baumgardt</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=JeffBaumgardt" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=JeffBaumgardt" title="Documentation">📖</a></td>
177
+ <td align="center" valign="top" width="14.28%"><a href="http://matchai.me"><img src="https://avatars0.githubusercontent.com/u/4658208?v=4?s=100" width="100px;" alt="Matan Kushner"/><br /><sub><b>Matan Kushner</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=matchai" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=matchai" title="Documentation">📖</a> <a href="#ideas-matchai" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=matchai" title="Tests">⚠️</a></td>
178
+ <td align="center" valign="top" width="14.28%"><a href="http://www.wendtedesigns.com/"><img src="https://avatars2.githubusercontent.com/u/5779538?v=4?s=100" width="100px;" alt="Alex Wendte"/><br /><sub><b>Alex Wendte</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=themostcolm" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=themostcolm" title="Documentation">📖</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=themostcolm" title="Tests">⚠️</a></td>
179
+ </tr>
180
+ <tr>
181
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/ruffle1986"><img src="https://avatars0.githubusercontent.com/u/2196208?v=4?s=100" width="100px;" alt="Tamas Fodor"/><br /><sub><b>Tamas Fodor</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=ruffle1986" title="Documentation">📖</a></td>
182
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/BenjaminEckardt"><img src="https://avatars3.githubusercontent.com/u/14793495?v=4?s=100" width="100px;" alt="Benjamin Eckardt"/><br /><sub><b>Benjamin Eckardt</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=BenjaminEckardt" title="Code">💻</a></td>
183
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/campbellr"><img src="https://avatars3.githubusercontent.com/u/205752?v=4?s=100" width="100px;" alt="Ryan Campbell"/><br /><sub><b>Ryan Campbell</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=campbellr" title="Documentation">📖</a></td>
184
+ <td align="center" valign="top" width="14.28%"><a href="https://taylor-briggs.com"><img src="https://avatars2.githubusercontent.com/u/1335519?v=4?s=100" width="100px;" alt="Taylor Briggs"/><br /><sub><b>Taylor Briggs</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=TaylorBriggs" title="Tests">⚠️</a></td>
185
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/jgoz"><img src="https://avatars2.githubusercontent.com/u/132233?v=4?s=100" width="100px;" alt="John Gozde"/><br /><sub><b>John Gozde</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jgoz" title="Code">💻</a></td>
186
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/chentsulin"><img src="https://avatars2.githubusercontent.com/u/3382565?v=4?s=100" width="100px;" alt="C. T. Lin"/><br /><sub><b>C. T. Lin</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=chentsulin" title="Documentation">📖</a></td>
187
+ <td align="center" valign="top" width="14.28%"><a href="http://terrencewwong.com"><img src="https://avatars3.githubusercontent.com/u/5312329?v=4?s=100" width="100px;" alt="Terrence Wong"/><br /><sub><b>Terrence Wong</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=terrencewwong" title="Code">💻</a></td>
188
+ </tr>
189
+ <tr>
190
+ <td align="center" valign="top" width="14.28%"><a href="https://www.ossfinder.com"><img src="https://avatars0.githubusercontent.com/u/12230408?v=4?s=100" width="100px;" alt="Soo Jae Hwang"/><br /><sub><b>Soo Jae Hwang</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=misoguy" title="Code">💻</a></td>
191
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/RoystonS"><img src="https://avatars0.githubusercontent.com/u/19773?v=4?s=100" width="100px;" alt="Royston Shufflebotham"/><br /><sub><b>Royston Shufflebotham</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3ARoystonS" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=RoystonS" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=RoystonS" title="Documentation">📖</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=RoystonS" title="Tests">⚠️</a></td>
192
+ <td align="center" valign="top" width="14.28%"><a href="http://www.vadimbrodsky.com"><img src="https://avatars0.githubusercontent.com/u/591673?v=4?s=100" width="100px;" alt="Vadim Brodsky"/><br /><sub><b>Vadim Brodsky</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=VadimBrodsky" title="Code">💻</a></td>
193
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/eunjae_lee"><img src="https://avatars3.githubusercontent.com/u/499898?v=4?s=100" width="100px;" alt="Eunjae Lee"/><br /><sub><b>Eunjae Lee</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=eunjae-lee" title="Code">💻</a></td>
194
+ <td align="center" valign="top" width="14.28%"><a href="http://davidpeter.me"><img src="https://avatars2.githubusercontent.com/u/167743?v=4?s=100" width="100px;" alt="David Peter"/><br /><sub><b>David Peter</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=sarenji" title="Code">💻</a></td>
195
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/@puemos"><img src="https://avatars0.githubusercontent.com/u/13174025?v=4?s=100" width="100px;" alt="Shy Alter"/><br /><sub><b>Shy Alter</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=puemos" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=puemos" title="Documentation">📖</a></td>
196
+ <td align="center" valign="top" width="14.28%"><a href="https://lukaszmakuch.pl"><img src="https://avatars1.githubusercontent.com/u/11966621?v=4?s=100" width="100px;" alt="Łukasz Makuch"/><br /><sub><b>Łukasz Makuch</b></sub></a><br /><a href="#platform-lukaszmakuch" title="Packaging/porting to new platform">📦</a></td>
197
+ </tr>
198
+ <tr>
199
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/tylerthehaas"><img src="https://avatars1.githubusercontent.com/u/11150235?v=4?s=100" width="100px;" alt="Tyler Haas"/><br /><sub><b>Tyler Haas</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=tylerthehaas" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=tylerthehaas" title="Tests">⚠️</a></td>
200
+ <td align="center" valign="top" width="14.28%"><a href="http://vesalaakso.com"><img src="https://avatars2.githubusercontent.com/u/482561?v=4?s=100" width="100px;" alt="Vesa Laakso"/><br /><sub><b>Vesa Laakso</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=valscion" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=valscion" title="Tests">⚠️</a></td>
201
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Tolsee"><img src="https://avatars0.githubusercontent.com/u/16590492?v=4?s=100" width="100px;" alt="Tulsi Sapkota"/><br /><sub><b>Tulsi Sapkota</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Tolsee" title="Code">💻</a></td>
202
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/tnunes"><img src="https://avatars1.githubusercontent.com/u/163187?v=4?s=100" width="100px;" alt="Tiago Nunes"/><br /><sub><b>Tiago Nunes</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=tnunes" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=tnunes" title="Tests">⚠️</a></td>
203
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/JaxCavalera"><img src="https://avatars1.githubusercontent.com/u/15429762?v=4?s=100" width="100px;" alt="JaxCavalera"/><br /><sub><b>JaxCavalera</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=JaxCavalera" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/pulls?q=is%3Apr+reviewed-by%3AJaxCavalera" title="Reviewed Pull Requests">👀</a></td>
204
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/bopfer"><img src="https://avatars2.githubusercontent.com/u/824368?v=4?s=100" width="100px;" alt="bopfer"/><br /><sub><b>bopfer</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=bopfer" title="Tests">⚠️</a></td>
205
+ <td align="center" valign="top" width="14.28%"><a href="http://blog.alfrescian.com"><img src="https://avatars0.githubusercontent.com/u/1340740?v=4?s=100" width="100px;" alt="Jan Pfitzner"/><br /><sub><b>Jan Pfitzner</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=alfrescian" title="Code">💻</a></td>
206
+ </tr>
207
+ <tr>
208
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/dbismut"><img src="https://avatars2.githubusercontent.com/u/5003380?v=4?s=100" width="100px;" alt="David"/><br /><sub><b>David</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=dbismut" title="Code">💻</a></td>
209
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/diego_codes"><img src="https://avatars0.githubusercontent.com/u/5973294?v=4?s=100" width="100px;" alt="Diego Hernandez"/><br /><sub><b>Diego Hernandez</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=diego-codes" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=diego-codes" title="Tests">⚠️</a></td>
210
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/foray1010"><img src="https://avatars3.githubusercontent.com/u/3212221?v=4?s=100" width="100px;" alt="Alex Young"/><br /><sub><b>Alex Young</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=foray1010" title="Code">💻</a></td>
211
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/paularmstrong"><img src="https://avatars1.githubusercontent.com/u/33297?v=4?s=100" width="100px;" alt="Paul Armstrong"/><br /><sub><b>Paul Armstrong</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=paularmstrong" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=paularmstrong" title="Tests">⚠️</a></td>
212
+ <td align="center" valign="top" width="14.28%"><a href="https://hu.linkedin.com/pub/tamas-szabo/57/a4b/242"><img src="https://avatars0.githubusercontent.com/u/3720079?v=4?s=100" width="100px;" alt="Tamás Szabó"/><br /><sub><b>Tamás Szabó</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=szabototo89" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=szabototo89" title="Tests">⚠️</a></td>
213
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/dylan_piercey"><img src="https://avatars2.githubusercontent.com/u/4985201?v=4?s=100" width="100px;" alt="Dylan Piercey"/><br /><sub><b>Dylan Piercey</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=DylanPiercey" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=DylanPiercey" title="Tests">⚠️</a></td>
214
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/michaellasky"><img src="https://avatars2.githubusercontent.com/u/6646599?v=4?s=100" width="100px;" alt="Michael Lasky"/><br /><sub><b>Michael Lasky</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=michaellasky" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=michaellasky" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=michaellasky" title="Documentation">📖</a></td>
215
+ </tr>
216
+ <tr>
217
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/sebsilbermann"><img src="https://avatars3.githubusercontent.com/u/12292047?v=4?s=100" width="100px;" alt="Sebastian Silbermann"/><br /><sub><b>Sebastian Silbermann</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=eps1lon" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=eps1lon" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=eps1lon" title="Documentation">📖</a> <a href="#infra-eps1lon" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/testing-library/dom-testing-library/pulls?q=is%3Apr+reviewed-by%3Aeps1lon" title="Reviewed Pull Requests">👀</a></td>
218
+ <td align="center" valign="top" width="14.28%"><a href="https://dylanvann.com/"><img src="https://avatars0.githubusercontent.com/u/1537615?v=4?s=100" width="100px;" alt="Dylan Vann"/><br /><sub><b>Dylan Vann</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=DylanVann" title="Code">💻</a></td>
219
+ <td align="center" valign="top" width="14.28%"><a href="https://afontcu.dev"><img src="https://avatars0.githubusercontent.com/u/9197791?v=4?s=100" width="100px;" alt="Adrià Fontcuberta"/><br /><sub><b>Adrià Fontcuberta</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=afontcu" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=afontcu" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=afontcu" title="Documentation">📖</a></td>
220
+ <td align="center" valign="top" width="14.28%"><a href="http://thomlom.dev"><img src="https://avatars3.githubusercontent.com/u/16003285?v=4?s=100" width="100px;" alt="Thomas Lombart"/><br /><sub><b>Thomas Lombart</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=thomlom" title="Code">💻</a></td>
221
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/SavePointSam"><img src="https://avatars0.githubusercontent.com/u/8203211?v=4?s=100" width="100px;" alt="Sam Horton"/><br /><sub><b>Sam Horton</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=SavePointSam" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=SavePointSam" title="Tests">⚠️</a></td>
222
+ <td align="center" valign="top" width="14.28%"><a href="http://andrewhillcode.com"><img src="https://avatars1.githubusercontent.com/u/12396191?v=4?s=100" width="100px;" alt="Andrew Hill"/><br /><sub><b>Andrew Hill</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=andrewhillcode" title="Code">💻</a></td>
223
+ <td align="center" valign="top" width="14.28%"><a href="https://amann.me"><img src="https://avatars1.githubusercontent.com/u/4038316?v=4?s=100" width="100px;" alt="Jan Amann"/><br /><sub><b>Jan Amann</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=amannn" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=amannn" title="Tests">⚠️</a></td>
224
+ </tr>
225
+ <tr>
226
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/brapifra"><img src="https://avatars3.githubusercontent.com/u/17855450?v=4?s=100" width="100px;" alt="Brais Piñeiro"/><br /><sub><b>Brais Piñeiro</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=brapifra" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=brapifra" title="Tests">⚠️</a></td>
227
+ <td align="center" valign="top" width="14.28%"><a href="https://www.dominykas.com/"><img src="https://avatars1.githubusercontent.com/u/505619?v=4?s=100" width="100px;" alt="Dominykas Blyžė"/><br /><sub><b>Dominykas Blyžė</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=dominykas" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=dominykas" title="Tests">⚠️</a></td>
228
+ <td align="center" valign="top" width="14.28%"><a href="http://olzhas.de"><img src="https://avatars3.githubusercontent.com/u/15848876?v=4?s=100" width="100px;" alt="Olzhas Askar"/><br /><sub><b>Olzhas Askar</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=pheeria" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=pheeria" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=pheeria" title="Documentation">📖</a></td>
229
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/mbelsky_"><img src="https://avatars1.githubusercontent.com/u/3923527?v=4?s=100" width="100px;" alt="Max Belsky"/><br /><sub><b>Max Belsky</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=mbelsky" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=mbelsky" title="Tests">⚠️</a></td>
230
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/mmantel"><img src="https://avatars2.githubusercontent.com/u/1326403?v=4?s=100" width="100px;" alt="Michael Mantel"/><br /><sub><b>Michael Mantel</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=mmantel" title="Tests">⚠️</a></td>
231
+ <td align="center" valign="top" width="14.28%"><a href="https://tomdoes.tech/"><img src="https://avatars1.githubusercontent.com/u/8683577?v=4?s=100" width="100px;" alt="Tom Nagle"/><br /><sub><b>Tom Nagle</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=tomanagle" title="Code">💻</a></td>
232
+ <td align="center" valign="top" width="14.28%"><a href="http://westbrookjohnson.com"><img src="https://avatars0.githubusercontent.com/u/1156657?v=4?s=100" width="100px;" alt="Westbrook Johnson"/><br /><sub><b>Westbrook Johnson</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Westbrook" title="Code">💻</a></td>
233
+ </tr>
234
+ <tr>
235
+ <td align="center" valign="top" width="14.28%"><a href="https://aziz.js.org"><img src="https://avatars3.githubusercontent.com/u/17024120?v=4?s=100" width="100px;" alt="Mohammad Aziz"/><br /><sub><b>Mohammad Aziz</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=iAziz786" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=iAziz786" title="Tests">⚠️</a></td>
236
+ <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/seetdev/"><img src="https://avatars2.githubusercontent.com/u/35116035?v=4?s=100" width="100px;" alt="seetdev"/><br /><sub><b>seetdev</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=seetdev" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=seetdev" title="Code">💻</a></td>
237
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/xgbuils"><img src="https://avatars2.githubusercontent.com/u/6483614?v=4?s=100" width="100px;" alt="Xavier Garcia Buils"/><br /><sub><b>Xavier Garcia Buils</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=xgbuils" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=xgbuils" title="Tests">⚠️</a></td>
238
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/aw-davidson"><img src="https://avatars2.githubusercontent.com/u/32170938?v=4?s=100" width="100px;" alt="aw-davidson"/><br /><sub><b>aw-davidson</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=aw-davidson" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=aw-davidson" title="Tests">⚠️</a></td>
239
+ <td align="center" valign="top" width="14.28%"><a href="https://michaeldeboey.be"><img src="https://avatars3.githubusercontent.com/u/6643991?v=4?s=100" width="100px;" alt="Michaël De Boey"/><br /><sub><b>Michaël De Boey</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=MichaelDeBoey" title="Code">💻</a></td>
240
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/minh_ngvyen"><img src="https://avatars3.githubusercontent.com/u/2852660?v=4?s=100" width="100px;" alt="Minh Nguyen"/><br /><sub><b>Minh Nguyen</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=NMinhNguyen" title="Code">💻</a></td>
241
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/egilsster"><img src="https://avatars0.githubusercontent.com/u/5672257?v=4?s=100" width="100px;" alt="Egill Sveinbjörnsson"/><br /><sub><b>Egill Sveinbjörnsson</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=egilsster" title="Code">💻</a></td>
242
+ </tr>
243
+ <tr>
244
+ <td align="center" valign="top" width="14.28%"><a href="http://pustovalov.dev"><img src="https://avatars2.githubusercontent.com/u/1568885?v=4?s=100" width="100px;" alt="Pavel Pustovalov"/><br /><sub><b>Pavel Pustovalov</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=pustovalov" title="Documentation">📖</a></td>
245
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/apalaniuk"><img src="https://avatars1.githubusercontent.com/u/17710124?v=4?s=100" width="100px;" alt="Adam Palaniuk"/><br /><sub><b>Adam Palaniuk</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=apalaniuk" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=apalaniuk" title="Tests">⚠️</a></td>
246
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Yama-Tomo"><img src="https://avatars0.githubusercontent.com/u/4970917?v=4?s=100" width="100px;" alt="Yama-Tomo"/><br /><sub><b>Yama-Tomo</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Yama-Tomo" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=Yama-Tomo" title="Tests">⚠️</a></td>
247
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/airjp73"><img src="https://avatars2.githubusercontent.com/u/25882770?v=4?s=100" width="100px;" alt="Aaron Pettengill"/><br /><sub><b>Aaron Pettengill</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=airjp73" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=airjp73" title="Tests">⚠️</a></td>
248
+ <td align="center" valign="top" width="14.28%"><a href="http://kwboyd.com"><img src="https://avatars0.githubusercontent.com/u/13855750?v=4?s=100" width="100px;" alt="Kate W. Boyd"/><br /><sub><b>Kate W. Boyd</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=kwboyd" title="Code">💻</a></td>
249
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/rahulchavan30"><img src="https://avatars2.githubusercontent.com/u/5296464?v=4?s=100" width="100px;" alt="Rahul Suryakanth"/><br /><sub><b>Rahul Suryakanth</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=rahulchavan30" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=rahulchavan30" title="Tests">⚠️</a></td>
250
+ <td align="center" valign="top" width="14.28%"><a href="https://jamie.tokyo"><img src="https://avatars0.githubusercontent.com/u/5964236?v=4?s=100" width="100px;" alt="Jamie"/><br /><sub><b>Jamie</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jamsinclair" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=jamsinclair" title="Tests">⚠️</a></td>
251
+ </tr>
252
+ <tr>
253
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/nstepien"><img src="https://avatars0.githubusercontent.com/u/567105?v=4?s=100" width="100px;" alt="Nicolas Stepien"/><br /><sub><b>Nicolas Stepien</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=nstepien" title="Code">💻</a></td>
254
+ <td align="center" valign="top" width="14.28%"><a href="https://knpw.rs"><img src="https://avatars0.githubusercontent.com/u/174864?v=4?s=100" width="100px;" alt="Ken Powers"/><br /><sub><b>Ken Powers</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=knpwrs" title="Code">💻</a></td>
255
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/mzdunek93"><img src="https://avatars0.githubusercontent.com/u/10826511?v=4?s=100" width="100px;" alt="Michał Zdunek"/><br /><sub><b>Michał Zdunek</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=mzdunek93" title="Code">💻</a></td>
256
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Lagily"><img src="https://avatars2.githubusercontent.com/u/42535205?v=4?s=100" width="100px;" alt="Ali Nasserzadeh"/><br /><sub><b>Ali Nasserzadeh</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Lagily" title="Code">💻</a></td>
257
+ <td align="center" valign="top" width="14.28%"><a href="https://darekkay.com"><img src="https://avatars0.githubusercontent.com/u/3101914?v=4?s=100" width="100px;" alt="Darek Kay"/><br /><sub><b>Darek Kay</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=darekkay" title="Documentation">📖</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=darekkay" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=darekkay" title="Tests">⚠️</a></td>
258
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Lukas-Kullmann"><img src="https://avatars0.githubusercontent.com/u/387547?v=4?s=100" width="100px;" alt="Lukas"/><br /><sub><b>Lukas</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Lukas-Kullmann" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=Lukas-Kullmann" title="Tests">⚠️</a></td>
259
+ <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/pelotom"><img src="https://avatars2.githubusercontent.com/u/128019?v=4?s=100" width="100px;" alt="Tom Crockett"/><br /><sub><b>Tom Crockett</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=pelotom" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=pelotom" title="Tests">⚠️</a></td>
260
+ </tr>
261
+ <tr>
262
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/appleJax"><img src="https://avatars1.githubusercontent.com/u/13618860?v=4?s=100" width="100px;" alt="Kevin Brewer"/><br /><sub><b>Kevin Brewer</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=appleJax" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=appleJax" title="Tests">⚠️</a></td>
263
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/benmonro"><img src="https://avatars3.githubusercontent.com/u/399236?v=4?s=100" width="100px;" alt="Ben Monro"/><br /><sub><b>Ben Monro</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=benmonro" title="Code">💻</a> <a href="#ideas-benmonro" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=benmonro" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=benmonro" title="Documentation">📖</a></td>
264
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/smeijer"><img src="https://avatars1.githubusercontent.com/u/1196524?v=4?s=100" width="100px;" alt="Stephan Meijer"/><br /><sub><b>Stephan Meijer</b></sub></a><br /><a href="#ideas-smeijer" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=smeijer" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=smeijer" title="Tests">⚠️</a></td>
265
+ <td align="center" valign="top" width="14.28%"><a href="https://joaoforja.com/"><img src="https://avatars2.githubusercontent.com/u/7002157?v=4?s=100" width="100px;" alt="João Forja"/><br /><sub><b>João Forja</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Jnforja" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=Jnforja" title="Tests">⚠️</a></td>
266
+ <td align="center" valign="top" width="14.28%"><a href="https://nickmccurdy.com/"><img src="https://avatars0.githubusercontent.com/u/927220?v=4?s=100" width="100px;" alt="Nick McCurdy"/><br /><sub><b>Nick McCurdy</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=nickmccurdy" title="Documentation">📖</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=nickmccurdy" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=nickmccurdy" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/pulls?q=is%3Apr+reviewed-by%3Anickmccurdy" title="Reviewed Pull Requests">👀</a> <a href="#infra-nickmccurdy" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
267
+ <td align="center" valign="top" width="14.28%"><a href="http://calebmer.com"><img src="https://avatars1.githubusercontent.com/u/8282507?v=4?s=100" width="100px;" alt="Caleb Meredith"/><br /><sub><b>Caleb Meredith</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=calebmer" title="Code">💻</a></td>
268
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/marcosvega91"><img src="https://avatars2.githubusercontent.com/u/5365582?v=4?s=100" width="100px;" alt="Marco Moretti"/><br /><sub><b>Marco Moretti</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=marcosvega91" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=marcosvega91" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/pulls?q=is%3Apr+reviewed-by%3Amarcosvega91" title="Reviewed Pull Requests">👀</a></td>
269
+ </tr>
270
+ <tr>
271
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/tjefferson08"><img src="https://avatars2.githubusercontent.com/u/3535390?v=4?s=100" width="100px;" alt="Travis Jefferson"/><br /><sub><b>Travis Jefferson</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=tjefferson08" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=tjefferson08" title="Tests">⚠️</a></td>
272
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/mdjastrzebski"><img src="https://avatars2.githubusercontent.com/u/6368606?v=4?s=100" width="100px;" alt="Maciej Jastrzebski"/><br /><sub><b>Maciej Jastrzebski</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Amdjastrzebski" title="Bug reports">🐛</a></td>
273
+ <td align="center" valign="top" width="14.28%"><a href="https://commonlit.org"><img src="https://avatars3.githubusercontent.com/u/319471?v=4?s=100" width="100px;" alt="Geoff Harcourt"/><br /><sub><b>Geoff Harcourt</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=geoffharcourt" title="Code">💻</a></td>
274
+ <td align="center" valign="top" width="14.28%"><a href="http://www.joshuakgoldberg.com"><img src="https://avatars1.githubusercontent.com/u/3335181?v=4?s=100" width="100px;" alt="Josh Goldberg"/><br /><sub><b>Josh Goldberg</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=JoshuaKGoldberg" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=JoshuaKGoldberg" title="Tests">⚠️</a></td>
275
+ <td align="center" valign="top" width="14.28%"><a href="http://kengregory.com"><img src="https://avatars0.githubusercontent.com/u/3155127?v=4?s=100" width="100px;" alt="Ken Gregory"/><br /><sub><b>Ken Gregory</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=kgregory" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=kgregory" title="Tests">⚠️</a></td>
276
+ <td align="center" valign="top" width="14.28%"><a href="https://www.jacobparis.com/"><img src="https://avatars2.githubusercontent.com/u/5633704?v=4?s=100" width="100px;" alt="Jacob Paris"/><br /><sub><b>Jacob Paris</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=JacobParis" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=JacobParis" title="Tests">⚠️</a></td>
277
+ <td align="center" valign="top" width="14.28%"><a href="https://keiya01.github.io/portfolio"><img src="https://avatars1.githubusercontent.com/u/34934510?v=4?s=100" width="100px;" alt="keiya sasaki"/><br /><sub><b>keiya sasaki</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=keiya01" title="Documentation">📖</a></td>
278
+ </tr>
279
+ <tr>
280
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/idanen"><img src="https://avatars2.githubusercontent.com/u/1687893?v=4?s=100" width="100px;" alt="Idan Entin"/><br /><sub><b>Idan Entin</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=idanen" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=idanen" title="Tests">⚠️</a></td>
281
+ <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/deniz-susman-92b40a145/"><img src="https://avatars1.githubusercontent.com/u/39295979?v=4?s=100" width="100px;" alt="Deniz Susman"/><br /><sub><b>Deniz Susman</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=DenrizSusam" title="Code">💻</a></td>
282
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/delca85"><img src="https://avatars1.githubusercontent.com/u/4076043?v=4?s=100" width="100px;" alt="Bianca Del Carretto"/><br /><sub><b>Bianca Del Carretto</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=delca85" title="Tests">⚠️</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=delca85" title="Code">💻</a></td>
283
+ <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/joshlalonde3/"><img src="https://avatars3.githubusercontent.com/u/9097492?v=4?s=100" width="100px;" alt="Josh Lalonde"/><br /><sub><b>Josh Lalonde</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=ryuuji3" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=ryuuji3" title="Tests">⚠️</a></td>
284
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/ipap360"><img src="https://avatars2.githubusercontent.com/u/11017666?v=4?s=100" width="100px;" alt="Ioannis Papadopoulos"/><br /><sub><b>Ioannis Papadopoulos</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=ipap360" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=ipap360" title="Tests">⚠️</a></td>
285
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/maxnewlands"><img src="https://avatars3.githubusercontent.com/u/1304166?v=4?s=100" width="100px;" alt="Maxwell Newlands"/><br /><sub><b>Maxwell Newlands</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=maxnewlands" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=maxnewlands" title="Tests">⚠️</a></td>
286
+ <td align="center" valign="top" width="14.28%"><a href="http://www.jaredlux.com"><img src="https://avatars0.githubusercontent.com/u/450478?v=4?s=100" width="100px;" alt="Jared Luxenberg"/><br /><sub><b>Jared Luxenberg</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jluxenberg" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=jluxenberg" title="Tests">⚠️</a></td>
287
+ </tr>
288
+ <tr>
289
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Snizhana"><img src="https://avatars3.githubusercontent.com/u/18139946?v=4?s=100" width="100px;" alt="snizhana"/><br /><sub><b>snizhana</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Snizhana" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=Snizhana" title="Tests">⚠️</a></td>
290
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/micha149"><img src="https://avatars2.githubusercontent.com/u/298880?v=4?s=100" width="100px;" alt="Michael van Engelshoven"/><br /><sub><b>Michael van Engelshoven</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/pulls?q=is%3Apr+reviewed-by%3Amicha149" title="Reviewed Pull Requests">👀</a></td>
291
+ <td align="center" valign="top" width="14.28%"><a href="https://ashertuggle.wixsite.com/portfolio"><img src="https://avatars2.githubusercontent.com/u/10679635?v=4?s=100" width="100px;" alt="Asher Tuggle"/><br /><sub><b>Asher Tuggle</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Aawesomeunleashed" title="Bug reports">🐛</a></td>
292
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/winterlamon"><img src="https://avatars0.githubusercontent.com/u/16295605?v=4?s=100" width="100px;" alt="Winter LaMon"/><br /><sub><b>Winter LaMon</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=winterlamon" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=winterlamon" title="Tests">⚠️</a></td>
293
+ <td align="center" valign="top" width="14.28%"><a href="http://victorandcode.com"><img src="https://avatars0.githubusercontent.com/u/18427801?v=4?s=100" width="100px;" alt="Victor Cordova"/><br /><sub><b>Victor Cordova</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=victorandcode" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=victorandcode" title="Tests">⚠️</a></td>
294
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/slowselfip"><img src="https://avatars3.githubusercontent.com/u/9762906?v=4?s=100" width="100px;" alt="slowselfip"/><br /><sub><b>slowselfip</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Aslowselfip" title="Bug reports">🐛</a></td>
295
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Semigradsky"><img src="https://avatars3.githubusercontent.com/u/1198848?v=4?s=100" width="100px;" alt="Dmitry Semigradsky"/><br /><sub><b>Dmitry Semigradsky</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Semigradsky" title="Code">💻</a></td>
296
+ </tr>
297
+ <tr>
298
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Tismas"><img src="https://avatars2.githubusercontent.com/u/13601275?v=4?s=100" width="100px;" alt="Adam"/><br /><sub><b>Adam</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Tismas" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=Tismas" title="Tests">⚠️</a></td>
299
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/balavishnuvj"><img src="https://avatars3.githubusercontent.com/u/13718688?v=4?s=100" width="100px;" alt="balavishnuvj"/><br /><sub><b>balavishnuvj</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=balavishnuvj" title="Code">💻</a></td>
300
+ <td align="center" valign="top" width="14.28%"><a href="https://chriscolborne.com"><img src="https://avatars2.githubusercontent.com/u/101371?v=4?s=100" width="100px;" alt="Chris Colborne"/><br /><sub><b>Chris Colborne</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=zorfling" title="Code">💻</a></td>
301
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/romain-trotard"><img src="https://avatars0.githubusercontent.com/u/17161484?v=4?s=100" width="100px;" alt="Romain Trotard"/><br /><sub><b>Romain Trotard</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=romain-trotard" title="Code">💻</a></td>
302
+ <td align="center" valign="top" width="14.28%"><a href="http://www.thomasmarshall.com"><img src="https://avatars0.githubusercontent.com/u/770763?v=4?s=100" width="100px;" alt="Thomas Marshall"/><br /><sub><b>Thomas Marshall</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=thomasmarshall" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=thomasmarshall" title="Tests">⚠️</a></td>
303
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/johnjesse"><img src="https://avatars1.githubusercontent.com/u/6839660?v=4?s=100" width="100px;" alt="johnjessewood"/><br /><sub><b>johnjessewood</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Ajohnjesse" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=johnjesse" title="Code">💻</a></td>
304
+ <td align="center" valign="top" width="14.28%"><a href="https://codepen.io/ariperkkio/"><img src="https://avatars2.githubusercontent.com/u/14806298?v=4?s=100" width="100px;" alt="Ari Perkkiö"/><br /><sub><b>Ari Perkkiö</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3AAriPerkkio" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=AriPerkkio" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=AriPerkkio" title="Documentation">📖</a></td>
305
+ </tr>
306
+ <tr>
307
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/nathanforce"><img src="https://avatars2.githubusercontent.com/u/6694194?v=4?s=100" width="100px;" alt="Nathan Force"/><br /><sub><b>Nathan Force</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=nathanforce" title="Code">💻</a></td>
308
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/ph-fritsche"><img src="https://avatars.githubusercontent.com/u/39068198?v=4?s=100" width="100px;" alt="Philipp Fritsche"/><br /><sub><b>Philipp Fritsche</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=ph-fritsche" title="Code">💻</a></td>
309
+ <td align="center" valign="top" width="14.28%"><a href="https://medium.com/@renatoalencar"><img src="https://avatars.githubusercontent.com/u/6964593?v=4?s=100" width="100px;" alt="Renato Alencar"/><br /><sub><b>Renato Alencar</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=renatoalencar" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=renatoalencar" title="Tests">⚠️</a></td>
310
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/SimenB"><img src="https://avatars.githubusercontent.com/u/1404810?v=4?s=100" width="100px;" alt="Simen Bekkhus"/><br /><sub><b>Simen Bekkhus</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3ASimenB" title="Bug reports">🐛</a></td>
311
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/gaearon"><img src="https://avatars.githubusercontent.com/u/810438?v=4?s=100" width="100px;" alt="Dan Abramov"/><br /><sub><b>Dan Abramov</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Agaearon" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/dom-testing-library/pulls?q=is%3Apr+reviewed-by%3Agaearon" title="Reviewed Pull Requests">👀</a></td>
312
+ <td align="center" valign="top" width="14.28%"><a href="https://matan.io"><img src="https://avatars.githubusercontent.com/u/12711091?v=4?s=100" width="100px;" alt="Matan Borenkraout"/><br /><sub><b>Matan Borenkraout</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=MatanBobi" title="Code">💻</a></td>
313
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/simcha90"><img src="https://avatars.githubusercontent.com/u/56388545?v=4?s=100" width="100px;" alt="simcha90"/><br /><sub><b>simcha90</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=simcha90" title="Code">💻</a></td>
314
+ </tr>
315
+ <tr>
316
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/amitmiran137"><img src="https://avatars.githubusercontent.com/u/47772523?v=4?s=100" width="100px;" alt="Amit Miran"/><br /><sub><b>Amit Miran</b></sub></a><br /><a href="#infra-amitmiran137" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
317
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/leschdom"><img src="https://avatars.githubusercontent.com/u/62334278?v=4?s=100" width="100px;" alt="Dominik Lesch"/><br /><sub><b>Dominik Lesch</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=leschdom" title="Documentation">📖</a></td>
318
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/G-Rath"><img src="https://avatars.githubusercontent.com/u/3151613?v=4?s=100" width="100px;" alt="Gareth Jones"/><br /><sub><b>Gareth Jones</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=G-Rath" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=G-Rath" title="Tests">⚠️</a></td>
319
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/riotrah"><img src="https://avatars.githubusercontent.com/u/22646419?v=4?s=100" width="100px;" alt="Rayat Rahman"/><br /><sub><b>Rayat Rahman</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=riotrah" title="Code">💻</a></td>
320
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/savcni01"><img src="https://avatars.githubusercontent.com/u/18025894?v=4?s=100" width="100px;" alt="Nik Savchenko"/><br /><sub><b>Nik Savchenko</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=savcni01" title="Code">💻</a></td>
321
+ <td align="center" valign="top" width="14.28%"><a href="http://www.hawkeye.dog"><img src="https://avatars.githubusercontent.com/u/7245931?v=4?s=100" width="100px;" alt="Kevin Fleischman"/><br /><sub><b>Kevin Fleischman</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=istateside" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/commits?author=istateside" title="Tests">⚠️</a></td>
322
+ <td align="center" valign="top" width="14.28%"><a href="http://dfdx.us"><img src="https://avatars.githubusercontent.com/u/3087358?v=4?s=100" width="100px;" alt="Beth Hitch"/><br /><sub><b>Beth Hitch</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=dfoverdx" title="Code">💻</a></td>
323
+ </tr>
324
+ <tr>
325
+ <td align="center" valign="top" width="14.28%"><a href="http://www.jacklaurence.net"><img src="https://avatars.githubusercontent.com/u/12763356?v=4?s=100" width="100px;" alt="Jack Laurence"/><br /><sub><b>Jack Laurence</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jacklaurencegaray" title="Code">💻</a></td>
326
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Lusito"><img src="https://avatars.githubusercontent.com/u/53570854?v=4?s=100" width="100px;" alt="SantoJambit"/><br /><sub><b>SantoJambit</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=SantoJambit" title="Code">💻</a></td>
327
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/mittalyashu"><img src="https://avatars.githubusercontent.com/u/29014463?v=4?s=100" width="100px;" alt="Yashu Mittal"/><br /><sub><b>Yashu Mittal</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=mittalyashu" title="Documentation">📖</a></td>
328
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/IanVS"><img src="https://avatars.githubusercontent.com/u/4616705?v=4?s=100" width="100px;" alt="Ian VanSchooten"/><br /><sub><b>Ian VanSchooten</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=IanVS" title="Code">💻</a></td>
329
+ <td align="center" valign="top" width="14.28%"><a href="http://supervanya.com"><img src="https://avatars.githubusercontent.com/u/12336038?v=4?s=100" width="100px;" alt="Vanya Prokopovich"/><br /><sub><b>Vanya Prokopovich</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Asupervanya" title="Bug reports">🐛</a></td>
330
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/jrnail23"><img src="https://avatars.githubusercontent.com/u/392612?v=4?s=100" width="100px;" alt="James Nail"/><br /><sub><b>James Nail</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Ajrnail23" title="Bug reports">🐛</a></td>
331
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/robcaldecott"><img src="https://avatars.githubusercontent.com/u/796702?v=4?s=100" width="100px;" alt="Rob Caldecott"/><br /><sub><b>Rob Caldecott</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Arobcaldecott" title="Bug reports">🐛</a></td>
332
+ </tr>
333
+ <tr>
334
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Dennis273"><img src="https://avatars.githubusercontent.com/u/19815164?v=4?s=100" width="100px;" alt="Dennis273"/><br /><sub><b>Dennis273</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Dennis273" title="Code">💻</a></td>
335
+ <td align="center" valign="top" width="14.28%"><a href="https://www.jacksonhardaker.dev"><img src="https://avatars.githubusercontent.com/u/7596320?v=4?s=100" width="100px;" alt="Jackson Hardaker"/><br /><sub><b>Jackson Hardaker</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jacksonhardaker" title="Tests">⚠️</a></td>
336
+ <td align="center" valign="top" width="14.28%"><a href="https://www.robin-drexler.com/"><img src="https://avatars.githubusercontent.com/u/474248?v=4?s=100" width="100px;" alt="Robin Drexler"/><br /><sub><b>Robin Drexler</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=robin-drexler" title="Code">💻</a></td>
337
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/dolevoper"><img src="https://avatars.githubusercontent.com/u/53278705?v=4?s=100" width="100px;" alt="Omer Dolev"/><br /><sub><b>Omer Dolev</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=dolevoper" title="Code">💻</a></td>
338
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Lirlev48"><img src="https://avatars.githubusercontent.com/u/58209233?v=4?s=100" width="100px;" alt="Lirlev48"/><br /><sub><b>Lirlev48</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Lirlev48" title="Code">💻</a></td>
339
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/kalmi"><img src="https://avatars.githubusercontent.com/u/54426?v=4?s=100" width="100px;" alt="Tarnay Kálmán"/><br /><sub><b>Tarnay Kálmán</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=kalmi" title="Code">💻</a></td>
340
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/MynockSpit"><img src="https://avatars.githubusercontent.com/u/5713867?v=4?s=100" width="100px;" alt="Than Hutchins"/><br /><sub><b>Than Hutchins</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=MynockSpit" title="Code">💻</a></td>
341
+ </tr>
342
+ <tr>
343
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/raplemie"><img src="https://avatars.githubusercontent.com/u/1904889?v=4?s=100" width="100px;" alt="Raphaël LEMIEUX"/><br /><sub><b>Raphaël LEMIEUX</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=raplemie" title="Code">💻</a></td>
344
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/arthurlvilasboas"><img src="https://avatars.githubusercontent.com/u/95368212?v=4?s=100" width="100px;" alt="Arthur Lauck Vilas Boas"/><br /><sub><b>Arthur Lauck Vilas Boas</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=arthurlvilasboas" title="Documentation">📖</a></td>
345
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/DaniAcu"><img src="https://avatars.githubusercontent.com/u/26409015?v=4?s=100" width="100px;" alt="Daniel Acuña"/><br /><sub><b>Daniel Acuña</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=DaniAcu" title="Code">💻</a></td>
346
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/jlp-craigmorten"><img src="https://avatars.githubusercontent.com/u/124147726?v=4?s=100" width="100px;" alt="Craig Morten"/><br /><sub><b>Craig Morten</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jlp-craigmorten" title="Code">💻</a> <a href="#question-jlp-craigmorten" title="Answering Questions">💬</a></td>
347
+ <td align="center" valign="top" width="14.28%"><a href="https://naor.dev"><img src="https://avatars.githubusercontent.com/u/6171622?v=4?s=100" width="100px;" alt="Naor Peled"/><br /><sub><b>Naor Peled</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=naorpeled" title="Code">💻</a></td>
348
+ <td align="center" valign="top" width="14.28%"><a href="http://everlong.org/"><img src="https://avatars.githubusercontent.com/u/454175?v=4?s=100" width="100px;" alt="Julien Wajsberg"/><br /><sub><b>Julien Wajsberg</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=julienw" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Ajulienw" title="Bug reports">🐛</a></td>
349
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/KevinBon"><img src="https://avatars.githubusercontent.com/u/1910927?v=4?s=100" width="100px;" alt="Kevin BON"/><br /><sub><b>Kevin BON</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=KevinBon" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3AKevinBon" title="Bug reports">🐛</a></td>
350
+ </tr>
351
+ <tr>
352
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/sieem"><img src="https://avatars.githubusercontent.com/u/36861085?v=4?s=100" width="100px;" alt="sieem"/><br /><sub><b>sieem</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=sieem" title="Code">💻</a></td>
353
+ </tr>
354
+ </tbody>
355
+ </table>
356
+
357
+ <!-- markdownlint-restore -->
358
+ <!-- prettier-ignore-end -->
359
+
360
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
361
+
362
+ This project follows the [all-contributors][all-contributors] specification.
363
+ Contributions of any kind welcome!
364
+
365
+ ## LICENSE
366
+
367
+ [MIT](LICENSE)
368
+
369
+ <!-- prettier-ignore-start -->
370
+
371
+ [npm]: https://www.npmjs.com/
372
+ [node]: https://nodejs.org
373
+ [build-badge]: https://img.shields.io/github/workflow/status/testing-library/dom-testing-library/validate?logo=github&style=flat-square
374
+ [build]: https://github.com/testing-library/dom-testing-library/actions?query=workflow%3Avalidate
375
+ [coverage-badge]: https://img.shields.io/codecov/c/github/testing-library/dom-testing-library.svg?style=flat-square
376
+ [coverage]: https://codecov.io/github/testing-library/dom-testing-library
377
+ [version-badge]: https://img.shields.io/npm/v/@testing-library/dom.svg?style=flat-square
378
+ [package]: https://www.npmjs.com/package/@testing-library/dom
379
+ [downloads-badge]: https://img.shields.io/npm/dm/@testing-library/dom.svg?style=flat-square
380
+ [npmtrends]: http://www.npmtrends.com/@testing-library/dom
381
+ [license-badge]: https://img.shields.io/npm/l/@testing-library/dom.svg?style=flat-square
382
+ [license]: https://github.com/testing-library/dom-testing-library/blob/main/LICENSE
383
+ [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
384
+ [prs]: http://makeapullrequest.com
385
+ [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
386
+ [coc]: https://github.com/testing-library/dom-testing-library/blob/main/CODE_OF_CONDUCT.md
387
+ [github-watch-badge]: https://img.shields.io/github/watchers/testing-library/dom-testing-library.svg?style=social
388
+ [github-watch]: https://github.com/testing-library/dom-testing-library/watchers
389
+ [github-star-badge]: https://img.shields.io/github/stars/testing-library/dom-testing-library.svg?style=social
390
+ [github-star]: https://github.com/testing-library/dom-testing-library/stargazers
391
+ [twitter]: https://twitter.com/intent/tweet?text=Check%20out%20dom-testing-library%20by%20%40testing-library%20https%3A%2F%2Fgithub.com%2Ftesting-library%2Fdom-testing-library%20%F0%9F%91%8D
392
+ [twitter-badge]: https://img.shields.io/twitter/url/https/github.com/testing-library/dom-testing-library.svg?style=social
393
+ [emojis]: https://github.com/all-contributors/all-contributors#emoji-key
394
+ [all-contributors]: https://github.com/all-contributors/all-contributors
395
+ [all-contributors-badge]: https://img.shields.io/github/all-contributors/testing-library/dom-testing-library?color=orange&style=flat-square
396
+ [set-immediate]: https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate
397
+ [guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
398
+ [jest]: https://facebook.github.io/jest
399
+ [discord-badge]: https://img.shields.io/discord/723559267868737556.svg?color=7389D8&labelColor=6A7EC2&logo=discord&logoColor=ffffff&style=flat-square
400
+ [discord]: https://discord.gg/testing-library
401
+
402
+ <!-- prettier-ignore-end -->
node_modules/@testing-library/dom/dist/@testing-library/dom.cjs.js ADDED
The diff for this file is too large to render. See raw diff
 
node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js ADDED
@@ -0,0 +1,2848 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as prettyFormat from 'pretty-format';
2
+ export { prettyFormat };
3
+ import { computeAccessibleName, computeAccessibleDescription } from 'dom-accessibility-api';
4
+ import { elementRoles, roles, roleElements } from 'aria-query';
5
+ import lzString from 'lz-string';
6
+
7
+ /**
8
+ * Source: https://github.com/facebook/jest/blob/e7bb6a1e26ffab90611b2593912df15b69315611/packages/pretty-format/src/plugins/DOMElement.ts
9
+ */
10
+ /* eslint-disable -- trying to stay as close to the original as possible */
11
+ /* istanbul ignore file */
12
+
13
+ function escapeHTML(str) {
14
+ return str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
15
+ }
16
+ // Return empty string if keys is empty.
17
+ const printProps = (keys, props, config, indentation, depth, refs, printer) => {
18
+ const indentationNext = indentation + config.indent;
19
+ const colors = config.colors;
20
+ return keys.map(key => {
21
+ const value = props[key];
22
+ let printed = printer(value, config, indentationNext, depth, refs);
23
+ if (typeof value !== 'string') {
24
+ if (printed.indexOf('\n') !== -1) {
25
+ printed = config.spacingOuter + indentationNext + printed + config.spacingOuter + indentation;
26
+ }
27
+ printed = '{' + printed + '}';
28
+ }
29
+ return config.spacingInner + indentation + colors.prop.open + key + colors.prop.close + '=' + colors.value.open + printed + colors.value.close;
30
+ }).join('');
31
+ };
32
+
33
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#node_type_constants
34
+ const NodeTypeTextNode = 3;
35
+
36
+ // Return empty string if children is empty.
37
+ const printChildren = (children, config, indentation, depth, refs, printer) => children.map(child => {
38
+ const printedChild = typeof child === 'string' ? printText(child, config) : printer(child, config, indentation, depth, refs);
39
+ if (printedChild === '' && typeof child === 'object' && child !== null && child.nodeType !== NodeTypeTextNode) {
40
+ // A plugin serialized this Node to '' meaning we should ignore it.
41
+ return '';
42
+ }
43
+ return config.spacingOuter + indentation + printedChild;
44
+ }).join('');
45
+ const printText = (text, config) => {
46
+ const contentColor = config.colors.content;
47
+ return contentColor.open + escapeHTML(text) + contentColor.close;
48
+ };
49
+ const printComment = (comment, config) => {
50
+ const commentColor = config.colors.comment;
51
+ return commentColor.open + '<!--' + escapeHTML(comment) + '-->' + commentColor.close;
52
+ };
53
+
54
+ // Separate the functions to format props, children, and element,
55
+ // so a plugin could override a particular function, if needed.
56
+ // Too bad, so sad: the traditional (but unnecessary) space
57
+ // in a self-closing tagColor requires a second test of printedProps.
58
+ const printElement = (type, printedProps, printedChildren, config, indentation) => {
59
+ const tagColor = config.colors.tag;
60
+ return tagColor.open + '<' + type + (printedProps && tagColor.close + printedProps + config.spacingOuter + indentation + tagColor.open) + (printedChildren ? '>' + tagColor.close + printedChildren + config.spacingOuter + indentation + tagColor.open + '</' + type : (printedProps && !config.min ? '' : ' ') + '/') + '>' + tagColor.close;
61
+ };
62
+ const printElementAsLeaf = (type, config) => {
63
+ const tagColor = config.colors.tag;
64
+ return tagColor.open + '<' + type + tagColor.close + ' …' + tagColor.open + ' />' + tagColor.close;
65
+ };
66
+ const ELEMENT_NODE$1 = 1;
67
+ const TEXT_NODE$1 = 3;
68
+ const COMMENT_NODE$1 = 8;
69
+ const FRAGMENT_NODE = 11;
70
+ const ELEMENT_REGEXP = /^((HTML|SVG)\w*)?Element$/;
71
+ const isCustomElement = val => {
72
+ const {
73
+ tagName
74
+ } = val;
75
+ return Boolean(typeof tagName === 'string' && tagName.includes('-') || typeof val.hasAttribute === 'function' && val.hasAttribute('is'));
76
+ };
77
+ const testNode = val => {
78
+ const constructorName = val.constructor.name;
79
+ const {
80
+ nodeType
81
+ } = val;
82
+ return nodeType === ELEMENT_NODE$1 && (ELEMENT_REGEXP.test(constructorName) || isCustomElement(val)) || nodeType === TEXT_NODE$1 && constructorName === 'Text' || nodeType === COMMENT_NODE$1 && constructorName === 'Comment' || nodeType === FRAGMENT_NODE && constructorName === 'DocumentFragment';
83
+ };
84
+ function nodeIsText(node) {
85
+ return node.nodeType === TEXT_NODE$1;
86
+ }
87
+ function nodeIsComment(node) {
88
+ return node.nodeType === COMMENT_NODE$1;
89
+ }
90
+ function nodeIsFragment(node) {
91
+ return node.nodeType === FRAGMENT_NODE;
92
+ }
93
+ function createDOMElementFilter(filterNode) {
94
+ return {
95
+ test: val => {
96
+ var _val$constructor2;
97
+ return ((val == null || (_val$constructor2 = val.constructor) == null ? void 0 : _val$constructor2.name) || isCustomElement(val)) && testNode(val);
98
+ },
99
+ serialize: (node, config, indentation, depth, refs, printer) => {
100
+ if (nodeIsText(node)) {
101
+ return printText(node.data, config);
102
+ }
103
+ if (nodeIsComment(node)) {
104
+ return printComment(node.data, config);
105
+ }
106
+ const type = nodeIsFragment(node) ? "DocumentFragment" : node.tagName.toLowerCase();
107
+ if (++depth > config.maxDepth) {
108
+ return printElementAsLeaf(type, config);
109
+ }
110
+ return printElement(type, printProps(nodeIsFragment(node) ? [] : Array.from(node.attributes).map(attr => attr.name).sort(), nodeIsFragment(node) ? {} : Array.from(node.attributes).reduce((props, attribute) => {
111
+ props[attribute.name] = attribute.value;
112
+ return props;
113
+ }, {}), config, indentation + config.indent, depth, refs, printer), printChildren(Array.prototype.slice.call(node.childNodes || node.children).filter(filterNode), config, indentation + config.indent, depth, refs, printer), config, indentation);
114
+ }
115
+ };
116
+ }
117
+
118
+ // We try to load node dependencies
119
+ let picocolors = null;
120
+ let readFileSync = null;
121
+ let codeFrameColumns = null;
122
+ try {
123
+ const nodeRequire = module && module.require;
124
+ readFileSync = nodeRequire.call(module, 'fs').readFileSync;
125
+ codeFrameColumns = nodeRequire.call(module, '@babel/code-frame').codeFrameColumns;
126
+ picocolors = nodeRequire.call(module, 'picocolors');
127
+ } catch {
128
+ // We're in a browser environment
129
+ }
130
+
131
+ // frame has the form "at myMethod (location/to/my/file.js:10:2)"
132
+ function getCodeFrame(frame) {
133
+ const locationStart = frame.indexOf('(') + 1;
134
+ const locationEnd = frame.indexOf(')');
135
+ const frameLocation = frame.slice(locationStart, locationEnd);
136
+ const frameLocationElements = frameLocation.split(':');
137
+ const [filename, line, column] = [frameLocationElements[0], parseInt(frameLocationElements[1], 10), parseInt(frameLocationElements[2], 10)];
138
+ let rawFileContents = '';
139
+ try {
140
+ rawFileContents = readFileSync(filename, 'utf-8');
141
+ } catch {
142
+ return '';
143
+ }
144
+ const codeFrame = codeFrameColumns(rawFileContents, {
145
+ start: {
146
+ line,
147
+ column
148
+ }
149
+ }, {
150
+ highlightCode: true,
151
+ linesBelow: 0
152
+ });
153
+ return picocolors.dim(frameLocation) + "\n" + codeFrame + "\n";
154
+ }
155
+ function getUserCodeFrame() {
156
+ // If we couldn't load dependencies, we can't generate the user trace
157
+ /* istanbul ignore next */
158
+ if (!readFileSync || !codeFrameColumns) {
159
+ return '';
160
+ }
161
+ const err = new Error();
162
+ const firstClientCodeFrame = err.stack.split('\n').slice(1) // Remove first line which has the form "Error: TypeError"
163
+ .find(frame => !frame.includes('node_modules/')); // Ignore frames from 3rd party libraries
164
+
165
+ return getCodeFrame(firstClientCodeFrame);
166
+ }
167
+
168
+ // Constant node.nodeType for text nodes, see:
169
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#Node_type_constants
170
+ const TEXT_NODE = 3;
171
+ function jestFakeTimersAreEnabled() {
172
+ /* istanbul ignore else */
173
+ // eslint-disable-next-line
174
+ if (typeof jest !== 'undefined' && jest !== null) {
175
+ return (
176
+ // legacy timers
177
+ setTimeout._isMockFunction === true ||
178
+ // modern timers
179
+ // eslint-disable-next-line prefer-object-has-own -- not supported by our support matrix
180
+ Object.prototype.hasOwnProperty.call(setTimeout, 'clock')
181
+ );
182
+ }
183
+ // istanbul ignore next
184
+ return false;
185
+ }
186
+ function getDocument() {
187
+ /* istanbul ignore if */
188
+ if (typeof window === 'undefined') {
189
+ throw new Error('Could not find default container');
190
+ }
191
+ return window.document;
192
+ }
193
+ function getWindowFromNode(node) {
194
+ if (node.defaultView) {
195
+ // node is document
196
+ return node.defaultView;
197
+ } else if (node.ownerDocument && node.ownerDocument.defaultView) {
198
+ // node is a DOM node
199
+ return node.ownerDocument.defaultView;
200
+ } else if (node.window) {
201
+ // node is window
202
+ return node.window;
203
+ } else if (node.ownerDocument && node.ownerDocument.defaultView === null) {
204
+ throw new Error("It looks like the window object is not available for the provided node.");
205
+ } else if (node.then instanceof Function) {
206
+ throw new Error("It looks like you passed a Promise object instead of a DOM node. Did you do something like `fireEvent.click(screen.findBy...` when you meant to use a `getBy` query `fireEvent.click(screen.getBy...`, or await the findBy query `fireEvent.click(await screen.findBy...`?");
207
+ } else if (Array.isArray(node)) {
208
+ throw new Error("It looks like you passed an Array instead of a DOM node. Did you do something like `fireEvent.click(screen.getAllBy...` when you meant to use a `getBy` query `fireEvent.click(screen.getBy...`?");
209
+ } else if (typeof node.debug === 'function' && typeof node.logTestingPlaygroundURL === 'function') {
210
+ throw new Error("It looks like you passed a `screen` object. Did you do something like `fireEvent.click(screen, ...` when you meant to use a query, e.g. `fireEvent.click(screen.getBy..., `?");
211
+ } else {
212
+ // The user passed something unusual to a calling function
213
+ throw new Error("The given node is not an Element, the node type is: " + typeof node + ".");
214
+ }
215
+ }
216
+ function checkContainerType(container) {
217
+ if (!container || !(typeof container.querySelector === 'function') || !(typeof container.querySelectorAll === 'function')) {
218
+ throw new TypeError("Expected container to be an Element, a Document or a DocumentFragment but got " + getTypeName(container) + ".");
219
+ }
220
+ function getTypeName(object) {
221
+ if (typeof object === 'object') {
222
+ return object === null ? 'null' : object.constructor.name;
223
+ }
224
+ return typeof object;
225
+ }
226
+ }
227
+
228
+ const shouldHighlight = () => {
229
+ if (typeof process === 'undefined') {
230
+ // Don't colorize in non-node environments (e.g. Browsers)
231
+ return false;
232
+ }
233
+ let colors;
234
+ // Try to safely parse env COLORS: We will default behavior if any step fails.
235
+ try {
236
+ var _process$env;
237
+ const colorsJSON = (_process$env = process.env) == null ? void 0 : _process$env.COLORS;
238
+ if (colorsJSON) {
239
+ colors = JSON.parse(colorsJSON);
240
+ }
241
+ } catch {
242
+ // If this throws, process.env?.COLORS wasn't parsable. Since we only
243
+ // care about `true` or `false`, we can safely ignore the error.
244
+ }
245
+ if (typeof colors === 'boolean') {
246
+ // If `colors` is set explicitly (both `true` and `false`), use that value.
247
+ return colors;
248
+ } else {
249
+ // If `colors` is not set, colorize if we're in node.
250
+ return process.versions !== undefined && process.versions.node !== undefined;
251
+ }
252
+ };
253
+ const {
254
+ DOMCollection
255
+ } = prettyFormat.plugins;
256
+
257
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#node_type_constants
258
+ const ELEMENT_NODE = 1;
259
+ const COMMENT_NODE = 8;
260
+
261
+ // https://github.com/facebook/jest/blob/615084195ae1ae61ddd56162c62bbdda17587569/packages/pretty-format/src/plugins/DOMElement.ts#L50
262
+ function filterCommentsAndDefaultIgnoreTagsTags(value) {
263
+ return value.nodeType !== COMMENT_NODE && (value.nodeType !== ELEMENT_NODE || !value.matches(getConfig().defaultIgnore));
264
+ }
265
+ function prettyDOM(dom, maxLength, options) {
266
+ if (options === void 0) {
267
+ options = {};
268
+ }
269
+ if (!dom) {
270
+ dom = getDocument().body;
271
+ }
272
+ if (typeof maxLength !== 'number') {
273
+ maxLength = typeof process !== 'undefined' && typeof process.env !== 'undefined' && process.env.DEBUG_PRINT_LIMIT || 7000;
274
+ }
275
+ if (maxLength === 0) {
276
+ return '';
277
+ }
278
+ if (dom.documentElement) {
279
+ dom = dom.documentElement;
280
+ }
281
+ let domTypeName = typeof dom;
282
+ if (domTypeName === 'object') {
283
+ domTypeName = dom.constructor.name;
284
+ } else {
285
+ // To don't fall with `in` operator
286
+ dom = {};
287
+ }
288
+ if (!('outerHTML' in dom)) {
289
+ throw new TypeError("Expected an element or document but got " + domTypeName);
290
+ }
291
+ const {
292
+ filterNode = filterCommentsAndDefaultIgnoreTagsTags,
293
+ ...prettyFormatOptions
294
+ } = options;
295
+ const debugContent = prettyFormat.format(dom, {
296
+ plugins: [createDOMElementFilter(filterNode), DOMCollection],
297
+ printFunctionName: false,
298
+ highlight: shouldHighlight(),
299
+ ...prettyFormatOptions
300
+ });
301
+ return maxLength !== undefined && dom.outerHTML.length > maxLength ? debugContent.slice(0, maxLength) + "..." : debugContent;
302
+ }
303
+ const logDOM = function () {
304
+ const userCodeFrame = getUserCodeFrame();
305
+ if (userCodeFrame) {
306
+ console.log(prettyDOM(...arguments) + "\n\n" + userCodeFrame);
307
+ } else {
308
+ console.log(prettyDOM(...arguments));
309
+ }
310
+ };
311
+
312
+ // It would be cleaner for this to live inside './queries', but
313
+ // other parts of the code assume that all exports from
314
+ // './queries' are query functions.
315
+ let config = {
316
+ testIdAttribute: 'data-testid',
317
+ asyncUtilTimeout: 1000,
318
+ // asyncWrapper and advanceTimersWrapper is to support React's async `act` function.
319
+ // forcing react-testing-library to wrap all async functions would've been
320
+ // a total nightmare (consider wrapping every findBy* query and then also
321
+ // updating `within` so those would be wrapped too. Total nightmare).
322
+ // so we have this config option that's really only intended for
323
+ // react-testing-library to use. For that reason, this feature will remain
324
+ // undocumented.
325
+ asyncWrapper: cb => cb(),
326
+ unstable_advanceTimersWrapper: cb => cb(),
327
+ eventWrapper: cb => cb(),
328
+ // default value for the `hidden` option in `ByRole` queries
329
+ defaultHidden: false,
330
+ // default value for the `ignore` option in `ByText` queries
331
+ defaultIgnore: 'script, style',
332
+ // showOriginalStackTrace flag to show the full error stack traces for async errors
333
+ showOriginalStackTrace: false,
334
+ // throw errors w/ suggestions for better queries. Opt in so off by default.
335
+ throwSuggestions: false,
336
+ // called when getBy* queries fail. (message, container) => Error
337
+ getElementError(message, container) {
338
+ const prettifiedDOM = prettyDOM(container);
339
+ const error = new Error([message, "Ignored nodes: comments, " + config.defaultIgnore + "\n" + prettifiedDOM].filter(Boolean).join('\n\n'));
340
+ error.name = 'TestingLibraryElementError';
341
+ return error;
342
+ },
343
+ _disableExpensiveErrorDiagnostics: false,
344
+ computedStyleSupportsPseudoElements: false
345
+ };
346
+ function runWithExpensiveErrorDiagnosticsDisabled(callback) {
347
+ try {
348
+ config._disableExpensiveErrorDiagnostics = true;
349
+ return callback();
350
+ } finally {
351
+ config._disableExpensiveErrorDiagnostics = false;
352
+ }
353
+ }
354
+ function configure(newConfig) {
355
+ if (typeof newConfig === 'function') {
356
+ // Pass the existing config out to the provided function
357
+ // and accept a delta in return
358
+ newConfig = newConfig(config);
359
+ }
360
+
361
+ // Merge the incoming config delta
362
+ config = {
363
+ ...config,
364
+ ...newConfig
365
+ };
366
+ }
367
+ function getConfig() {
368
+ return config;
369
+ }
370
+
371
+ const labelledNodeNames = ['button', 'meter', 'output', 'progress', 'select', 'textarea', 'input'];
372
+ function getTextContent(node) {
373
+ if (labelledNodeNames.includes(node.nodeName.toLowerCase())) {
374
+ return '';
375
+ }
376
+ if (node.nodeType === TEXT_NODE) return node.textContent;
377
+ return Array.from(node.childNodes).map(childNode => getTextContent(childNode)).join('');
378
+ }
379
+ function getLabelContent(element) {
380
+ let textContent;
381
+ if (element.tagName.toLowerCase() === 'label') {
382
+ textContent = getTextContent(element);
383
+ } else {
384
+ textContent = element.value || element.textContent;
385
+ }
386
+ return textContent;
387
+ }
388
+
389
+ // Based on https://github.com/eps1lon/dom-accessibility-api/pull/352
390
+ function getRealLabels(element) {
391
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- types are not aware of older browsers that don't implement `labels`
392
+ if (element.labels !== undefined) {
393
+ var _labels;
394
+ return (_labels = element.labels) != null ? _labels : [];
395
+ }
396
+ if (!isLabelable(element)) return [];
397
+ const labels = element.ownerDocument.querySelectorAll('label');
398
+ return Array.from(labels).filter(label => label.control === element);
399
+ }
400
+ function isLabelable(element) {
401
+ return /BUTTON|METER|OUTPUT|PROGRESS|SELECT|TEXTAREA/.test(element.tagName) || element.tagName === 'INPUT' && element.getAttribute('type') !== 'hidden';
402
+ }
403
+ function getLabels(container, element, _temp) {
404
+ let {
405
+ selector = '*'
406
+ } = _temp === void 0 ? {} : _temp;
407
+ const ariaLabelledBy = element.getAttribute('aria-labelledby');
408
+ const labelsId = ariaLabelledBy ? ariaLabelledBy.split(' ') : [];
409
+ return labelsId.length ? labelsId.map(labelId => {
410
+ const labellingElement = container.querySelector("[id=\"" + labelId + "\"]");
411
+ return labellingElement ? {
412
+ content: getLabelContent(labellingElement),
413
+ formControl: null
414
+ } : {
415
+ content: '',
416
+ formControl: null
417
+ };
418
+ }) : Array.from(getRealLabels(element)).map(label => {
419
+ const textToMatch = getLabelContent(label);
420
+ const formControlSelector = 'button, input, meter, output, progress, select, textarea';
421
+ const labelledFormControl = Array.from(label.querySelectorAll(formControlSelector)).filter(formControlElement => formControlElement.matches(selector))[0];
422
+ return {
423
+ content: textToMatch,
424
+ formControl: labelledFormControl
425
+ };
426
+ });
427
+ }
428
+
429
+ function assertNotNullOrUndefined(matcher) {
430
+ if (matcher === null || matcher === undefined) {
431
+ throw new Error(// eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- implicitly converting `T` to `string`
432
+ "It looks like " + matcher + " was passed instead of a matcher. Did you do something like getByText(" + matcher + ")?");
433
+ }
434
+ }
435
+ function fuzzyMatches(textToMatch, node, matcher, normalizer) {
436
+ if (typeof textToMatch !== 'string') {
437
+ return false;
438
+ }
439
+ assertNotNullOrUndefined(matcher);
440
+ const normalizedText = normalizer(textToMatch);
441
+ if (typeof matcher === 'string' || typeof matcher === 'number') {
442
+ return normalizedText.toLowerCase().includes(matcher.toString().toLowerCase());
443
+ } else if (typeof matcher === 'function') {
444
+ return matcher(normalizedText, node);
445
+ } else {
446
+ return matchRegExp(matcher, normalizedText);
447
+ }
448
+ }
449
+ function matches(textToMatch, node, matcher, normalizer) {
450
+ if (typeof textToMatch !== 'string') {
451
+ return false;
452
+ }
453
+ assertNotNullOrUndefined(matcher);
454
+ const normalizedText = normalizer(textToMatch);
455
+ if (matcher instanceof Function) {
456
+ return matcher(normalizedText, node);
457
+ } else if (matcher instanceof RegExp) {
458
+ return matchRegExp(matcher, normalizedText);
459
+ } else {
460
+ return normalizedText === String(matcher);
461
+ }
462
+ }
463
+ function getDefaultNormalizer(_temp) {
464
+ let {
465
+ trim = true,
466
+ collapseWhitespace = true
467
+ } = _temp === void 0 ? {} : _temp;
468
+ return text => {
469
+ let normalizedText = text;
470
+ normalizedText = trim ? normalizedText.trim() : normalizedText;
471
+ normalizedText = collapseWhitespace ? normalizedText.replace(/\s+/g, ' ') : normalizedText;
472
+ return normalizedText;
473
+ };
474
+ }
475
+
476
+ /**
477
+ * Constructs a normalizer to pass to functions in matches.js
478
+ * @param {boolean|undefined} trim The user-specified value for `trim`, without
479
+ * any defaulting having been applied
480
+ * @param {boolean|undefined} collapseWhitespace The user-specified value for
481
+ * `collapseWhitespace`, without any defaulting having been applied
482
+ * @param {Function|undefined} normalizer The user-specified normalizer
483
+ * @returns {Function} A normalizer
484
+ */
485
+
486
+ function makeNormalizer(_ref) {
487
+ let {
488
+ trim,
489
+ collapseWhitespace,
490
+ normalizer
491
+ } = _ref;
492
+ if (!normalizer) {
493
+ // No custom normalizer specified. Just use default.
494
+ return getDefaultNormalizer({
495
+ trim,
496
+ collapseWhitespace
497
+ });
498
+ }
499
+ if (typeof trim !== 'undefined' || typeof collapseWhitespace !== 'undefined') {
500
+ // They've also specified a value for trim or collapseWhitespace
501
+ throw new Error('trim and collapseWhitespace are not supported with a normalizer. ' + 'If you want to use the default trim and collapseWhitespace logic in your normalizer, ' + 'use "getDefaultNormalizer({trim, collapseWhitespace})" and compose that into your normalizer');
502
+ }
503
+ return normalizer;
504
+ }
505
+ function matchRegExp(matcher, text) {
506
+ const match = matcher.test(text);
507
+ if (matcher.global && matcher.lastIndex !== 0) {
508
+ console.warn("To match all elements we had to reset the lastIndex of the RegExp because the global flag is enabled. We encourage to remove the global flag from the RegExp.");
509
+ matcher.lastIndex = 0;
510
+ }
511
+ return match;
512
+ }
513
+
514
+ function getNodeText(node) {
515
+ if (node.matches('input[type=submit], input[type=button], input[type=reset]')) {
516
+ return node.value;
517
+ }
518
+ return Array.from(node.childNodes).filter(child => child.nodeType === TEXT_NODE && Boolean(child.textContent)).map(c => c.textContent).join('');
519
+ }
520
+
521
+ const elementRoleList = buildElementRoleList(elementRoles);
522
+
523
+ /**
524
+ * @param {Element} element -
525
+ * @returns {boolean} - `true` if `element` and its subtree are inaccessible
526
+ */
527
+ function isSubtreeInaccessible(element) {
528
+ if (element.hidden === true) {
529
+ return true;
530
+ }
531
+ if (element.getAttribute('aria-hidden') === 'true') {
532
+ return true;
533
+ }
534
+ const window = element.ownerDocument.defaultView;
535
+ if (window.getComputedStyle(element).display === 'none') {
536
+ return true;
537
+ }
538
+ return false;
539
+ }
540
+
541
+ /**
542
+ * Partial implementation https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
543
+ * which should only be used for elements with a non-presentational role i.e.
544
+ * `role="none"` and `role="presentation"` will not be excluded.
545
+ *
546
+ * Implements aria-hidden semantics (i.e. parent overrides child)
547
+ * Ignores "Child Presentational: True" characteristics
548
+ *
549
+ * @param {Element} element -
550
+ * @param {object} [options] -
551
+ * @param {function (element: Element): boolean} options.isSubtreeInaccessible -
552
+ * can be used to return cached results from previous isSubtreeInaccessible calls
553
+ * @returns {boolean} true if excluded, otherwise false
554
+ */
555
+ function isInaccessible(element, options) {
556
+ if (options === void 0) {
557
+ options = {};
558
+ }
559
+ const {
560
+ isSubtreeInaccessible: isSubtreeInaccessibleImpl = isSubtreeInaccessible
561
+ } = options;
562
+ const window = element.ownerDocument.defaultView;
563
+ // since visibility is inherited we can exit early
564
+ if (window.getComputedStyle(element).visibility === 'hidden') {
565
+ return true;
566
+ }
567
+ let currentElement = element;
568
+ while (currentElement) {
569
+ if (isSubtreeInaccessibleImpl(currentElement)) {
570
+ return true;
571
+ }
572
+ currentElement = currentElement.parentElement;
573
+ }
574
+ return false;
575
+ }
576
+ function getImplicitAriaRoles(currentNode) {
577
+ // eslint bug here:
578
+ // eslint-disable-next-line no-unused-vars
579
+ for (const {
580
+ match,
581
+ roles
582
+ } of elementRoleList) {
583
+ if (match(currentNode)) {
584
+ return [...roles];
585
+ }
586
+ }
587
+ return [];
588
+ }
589
+ function buildElementRoleList(elementRolesMap) {
590
+ function makeElementSelector(_ref) {
591
+ let {
592
+ name,
593
+ attributes
594
+ } = _ref;
595
+ return "" + name + attributes.map(_ref2 => {
596
+ let {
597
+ name: attributeName,
598
+ value,
599
+ constraints = []
600
+ } = _ref2;
601
+ const shouldNotExist = constraints.indexOf('undefined') !== -1;
602
+ const shouldBeNonEmpty = constraints.indexOf('set') !== -1;
603
+ const hasExplicitValue = typeof value !== 'undefined';
604
+ if (hasExplicitValue) {
605
+ return "[" + attributeName + "=\"" + value + "\"]";
606
+ } else if (shouldNotExist) {
607
+ return ":not([" + attributeName + "])";
608
+ } else if (shouldBeNonEmpty) {
609
+ return "[" + attributeName + "]:not([" + attributeName + "=\"\"])";
610
+ }
611
+ return "[" + attributeName + "]";
612
+ }).join('');
613
+ }
614
+ function getSelectorSpecificity(_ref3) {
615
+ let {
616
+ attributes = []
617
+ } = _ref3;
618
+ return attributes.length;
619
+ }
620
+ function bySelectorSpecificity(_ref4, _ref5) {
621
+ let {
622
+ specificity: leftSpecificity
623
+ } = _ref4;
624
+ let {
625
+ specificity: rightSpecificity
626
+ } = _ref5;
627
+ return rightSpecificity - leftSpecificity;
628
+ }
629
+ function match(element) {
630
+ let {
631
+ attributes = []
632
+ } = element;
633
+
634
+ // https://github.com/testing-library/dom-testing-library/issues/814
635
+ const typeTextIndex = attributes.findIndex(attribute => attribute.value && attribute.name === 'type' && attribute.value === 'text');
636
+ if (typeTextIndex >= 0) {
637
+ // not using splice to not mutate the attributes array
638
+ attributes = [...attributes.slice(0, typeTextIndex), ...attributes.slice(typeTextIndex + 1)];
639
+ }
640
+ const selector = makeElementSelector({
641
+ ...element,
642
+ attributes
643
+ });
644
+ return node => {
645
+ if (typeTextIndex >= 0 && node.type !== 'text') {
646
+ return false;
647
+ }
648
+ return node.matches(selector);
649
+ };
650
+ }
651
+ let result = [];
652
+
653
+ // eslint bug here:
654
+ // eslint-disable-next-line no-unused-vars
655
+ for (const [element, roles] of elementRolesMap.entries()) {
656
+ result = [...result, {
657
+ match: match(element),
658
+ roles: Array.from(roles),
659
+ specificity: getSelectorSpecificity(element)
660
+ }];
661
+ }
662
+ return result.sort(bySelectorSpecificity);
663
+ }
664
+ function getRoles(container, _temp) {
665
+ let {
666
+ hidden = false
667
+ } = _temp === void 0 ? {} : _temp;
668
+ function flattenDOM(node) {
669
+ return [node, ...Array.from(node.children).reduce((acc, child) => [...acc, ...flattenDOM(child)], [])];
670
+ }
671
+ return flattenDOM(container).filter(element => {
672
+ return hidden === false ? isInaccessible(element) === false : true;
673
+ }).reduce((acc, node) => {
674
+ let roles = [];
675
+ // TODO: This violates html-aria which does not allow any role on every element
676
+ if (node.hasAttribute('role')) {
677
+ roles = node.getAttribute('role').split(' ').slice(0, 1);
678
+ } else {
679
+ roles = getImplicitAriaRoles(node);
680
+ }
681
+ return roles.reduce((rolesAcc, role) => Array.isArray(rolesAcc[role]) ? {
682
+ ...rolesAcc,
683
+ [role]: [...rolesAcc[role], node]
684
+ } : {
685
+ ...rolesAcc,
686
+ [role]: [node]
687
+ }, acc);
688
+ }, {});
689
+ }
690
+ function prettyRoles(dom, _ref6) {
691
+ let {
692
+ hidden,
693
+ includeDescription
694
+ } = _ref6;
695
+ const roles = getRoles(dom, {
696
+ hidden
697
+ });
698
+ // We prefer to skip generic role, we don't recommend it
699
+ return Object.entries(roles).filter(_ref7 => {
700
+ let [role] = _ref7;
701
+ return role !== 'generic';
702
+ }).map(_ref8 => {
703
+ let [role, elements] = _ref8;
704
+ const delimiterBar = '-'.repeat(50);
705
+ const elementsString = elements.map(el => {
706
+ const nameString = "Name \"" + computeAccessibleName(el, {
707
+ computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
708
+ }) + "\":\n";
709
+ const domString = prettyDOM(el.cloneNode(false));
710
+ if (includeDescription) {
711
+ const descriptionString = "Description \"" + computeAccessibleDescription(el, {
712
+ computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
713
+ }) + "\":\n";
714
+ return "" + nameString + descriptionString + domString;
715
+ }
716
+ return "" + nameString + domString;
717
+ }).join('\n\n');
718
+ return role + ":\n\n" + elementsString + "\n\n" + delimiterBar;
719
+ }).join('\n');
720
+ }
721
+ const logRoles = function (dom, _temp2) {
722
+ let {
723
+ hidden = false
724
+ } = _temp2 === void 0 ? {} : _temp2;
725
+ return console.log(prettyRoles(dom, {
726
+ hidden
727
+ }));
728
+ };
729
+
730
+ /**
731
+ * @param {Element} element -
732
+ * @returns {boolean | undefined} - false/true if (not)selected, undefined if not selectable
733
+ */
734
+ function computeAriaSelected(element) {
735
+ // implicit value from html-aam mappings: https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
736
+ // https://www.w3.org/TR/html-aam-1.0/#details-id-97
737
+ if (element.tagName === 'OPTION') {
738
+ return element.selected;
739
+ }
740
+
741
+ // explicit value
742
+ return checkBooleanAttribute(element, 'aria-selected');
743
+ }
744
+
745
+ /**
746
+ * @param {Element} element -
747
+ * @returns {boolean} -
748
+ */
749
+ function computeAriaBusy(element) {
750
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-busy
751
+ return element.getAttribute('aria-busy') === 'true';
752
+ }
753
+
754
+ /**
755
+ * @param {Element} element -
756
+ * @returns {boolean | undefined} - false/true if (not)checked, undefined if not checked-able
757
+ */
758
+ function computeAriaChecked(element) {
759
+ // implicit value from html-aam mappings: https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
760
+ // https://www.w3.org/TR/html-aam-1.0/#details-id-56
761
+ // https://www.w3.org/TR/html-aam-1.0/#details-id-67
762
+ if ('indeterminate' in element && element.indeterminate) {
763
+ return undefined;
764
+ }
765
+ if ('checked' in element) {
766
+ return element.checked;
767
+ }
768
+
769
+ // explicit value
770
+ return checkBooleanAttribute(element, 'aria-checked');
771
+ }
772
+
773
+ /**
774
+ * @param {Element} element -
775
+ * @returns {boolean | undefined} - false/true if (not)pressed, undefined if not press-able
776
+ */
777
+ function computeAriaPressed(element) {
778
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-pressed
779
+ return checkBooleanAttribute(element, 'aria-pressed');
780
+ }
781
+
782
+ /**
783
+ * @param {Element} element -
784
+ * @returns {boolean | string | null} -
785
+ */
786
+ function computeAriaCurrent(element) {
787
+ var _ref9, _checkBooleanAttribut;
788
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-current
789
+ return (_ref9 = (_checkBooleanAttribut = checkBooleanAttribute(element, 'aria-current')) != null ? _checkBooleanAttribut : element.getAttribute('aria-current')) != null ? _ref9 : false;
790
+ }
791
+
792
+ /**
793
+ * @param {Element} element -
794
+ * @returns {boolean | undefined} - false/true if (not)expanded, undefined if not expand-able
795
+ */
796
+ function computeAriaExpanded(element) {
797
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-expanded
798
+ return checkBooleanAttribute(element, 'aria-expanded');
799
+ }
800
+ function checkBooleanAttribute(element, attribute) {
801
+ const attributeValue = element.getAttribute(attribute);
802
+ if (attributeValue === 'true') {
803
+ return true;
804
+ }
805
+ if (attributeValue === 'false') {
806
+ return false;
807
+ }
808
+ return undefined;
809
+ }
810
+
811
+ /**
812
+ * @param {Element} element -
813
+ * @returns {number | undefined} - number if implicit heading or aria-level present, otherwise undefined
814
+ */
815
+ function computeHeadingLevel(element) {
816
+ // https://w3c.github.io/html-aam/#el-h1-h6
817
+ // https://w3c.github.io/html-aam/#el-h1-h6
818
+ const implicitHeadingLevels = {
819
+ H1: 1,
820
+ H2: 2,
821
+ H3: 3,
822
+ H4: 4,
823
+ H5: 5,
824
+ H6: 6
825
+ };
826
+ // explicit aria-level value
827
+ // https://www.w3.org/TR/wai-aria-1.2/#aria-level
828
+ const ariaLevelAttribute = element.getAttribute('aria-level') && Number(element.getAttribute('aria-level'));
829
+ return ariaLevelAttribute || implicitHeadingLevels[element.tagName];
830
+ }
831
+
832
+ /**
833
+ * @param {Element} element -
834
+ * @returns {number | undefined} -
835
+ */
836
+ function computeAriaValueNow(element) {
837
+ const valueNow = element.getAttribute('aria-valuenow');
838
+ return valueNow === null ? undefined : +valueNow;
839
+ }
840
+
841
+ /**
842
+ * @param {Element} element -
843
+ * @returns {number | undefined} -
844
+ */
845
+ function computeAriaValueMax(element) {
846
+ const valueMax = element.getAttribute('aria-valuemax');
847
+ return valueMax === null ? undefined : +valueMax;
848
+ }
849
+
850
+ /**
851
+ * @param {Element} element -
852
+ * @returns {number | undefined} -
853
+ */
854
+ function computeAriaValueMin(element) {
855
+ const valueMin = element.getAttribute('aria-valuemin');
856
+ return valueMin === null ? undefined : +valueMin;
857
+ }
858
+
859
+ /**
860
+ * @param {Element} element -
861
+ * @returns {string | undefined} -
862
+ */
863
+ function computeAriaValueText(element) {
864
+ const valueText = element.getAttribute('aria-valuetext');
865
+ return valueText === null ? undefined : valueText;
866
+ }
867
+
868
+ const normalize = getDefaultNormalizer();
869
+ function escapeRegExp(string) {
870
+ return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
871
+ }
872
+ function getRegExpMatcher(string) {
873
+ return new RegExp(escapeRegExp(string.toLowerCase()), 'i');
874
+ }
875
+ function makeSuggestion(queryName, element, content, _ref) {
876
+ let {
877
+ variant,
878
+ name
879
+ } = _ref;
880
+ let warning = '';
881
+ const queryOptions = {};
882
+ const queryArgs = [['Role', 'TestId'].includes(queryName) ? content : getRegExpMatcher(content)];
883
+ if (name) {
884
+ queryOptions.name = getRegExpMatcher(name);
885
+ }
886
+ if (queryName === 'Role' && isInaccessible(element)) {
887
+ queryOptions.hidden = true;
888
+ warning = "Element is inaccessible. This means that the element and all its children are invisible to screen readers.\n If you are using the aria-hidden prop, make sure this is the right choice for your case.\n ";
889
+ }
890
+ if (Object.keys(queryOptions).length > 0) {
891
+ queryArgs.push(queryOptions);
892
+ }
893
+ const queryMethod = variant + "By" + queryName;
894
+ return {
895
+ queryName,
896
+ queryMethod,
897
+ queryArgs,
898
+ variant,
899
+ warning,
900
+ toString() {
901
+ if (warning) {
902
+ console.warn(warning);
903
+ }
904
+ let [text, options] = queryArgs;
905
+ text = typeof text === 'string' ? "'" + text + "'" : text;
906
+ options = options ? ", { " + Object.entries(options).map(_ref2 => {
907
+ let [k, v] = _ref2;
908
+ return k + ": " + v;
909
+ }).join(', ') + " }" : '';
910
+ return queryMethod + "(" + text + options + ")";
911
+ }
912
+ };
913
+ }
914
+ function canSuggest(currentMethod, requestedMethod, data) {
915
+ return data && (!requestedMethod || requestedMethod.toLowerCase() === currentMethod.toLowerCase());
916
+ }
917
+ function getSuggestedQuery(element, variant, method) {
918
+ var _element$getAttribute, _getImplicitAriaRoles;
919
+ if (variant === void 0) {
920
+ variant = 'get';
921
+ }
922
+ // don't create suggestions for script and style elements
923
+ if (element.matches(getConfig().defaultIgnore)) {
924
+ return undefined;
925
+ }
926
+
927
+ //We prefer to suggest something else if the role is generic
928
+ const role = (_element$getAttribute = element.getAttribute('role')) != null ? _element$getAttribute : (_getImplicitAriaRoles = getImplicitAriaRoles(element)) == null ? void 0 : _getImplicitAriaRoles[0];
929
+ if (role !== 'generic' && canSuggest('Role', method, role)) {
930
+ return makeSuggestion('Role', element, role, {
931
+ variant,
932
+ name: computeAccessibleName(element, {
933
+ computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
934
+ })
935
+ });
936
+ }
937
+ const labelText = getLabels(document, element).map(label => label.content).join(' ');
938
+ if (canSuggest('LabelText', method, labelText)) {
939
+ return makeSuggestion('LabelText', element, labelText, {
940
+ variant
941
+ });
942
+ }
943
+ const placeholderText = element.getAttribute('placeholder');
944
+ if (canSuggest('PlaceholderText', method, placeholderText)) {
945
+ return makeSuggestion('PlaceholderText', element, placeholderText, {
946
+ variant
947
+ });
948
+ }
949
+ const textContent = normalize(getNodeText(element));
950
+ if (canSuggest('Text', method, textContent)) {
951
+ return makeSuggestion('Text', element, textContent, {
952
+ variant
953
+ });
954
+ }
955
+ if (canSuggest('DisplayValue', method, element.value)) {
956
+ return makeSuggestion('DisplayValue', element, normalize(element.value), {
957
+ variant
958
+ });
959
+ }
960
+ const alt = element.getAttribute('alt');
961
+ if (canSuggest('AltText', method, alt)) {
962
+ return makeSuggestion('AltText', element, alt, {
963
+ variant
964
+ });
965
+ }
966
+ const title = element.getAttribute('title');
967
+ if (canSuggest('Title', method, title)) {
968
+ return makeSuggestion('Title', element, title, {
969
+ variant
970
+ });
971
+ }
972
+ const testId = element.getAttribute(getConfig().testIdAttribute);
973
+ if (canSuggest('TestId', method, testId)) {
974
+ return makeSuggestion('TestId', element, testId, {
975
+ variant
976
+ });
977
+ }
978
+ return undefined;
979
+ }
980
+
981
+ // This is so the stack trace the developer sees is one that's
982
+ // closer to their code (because async stack traces are hard to follow).
983
+ function copyStackTrace(target, source) {
984
+ target.stack = source.stack.replace(source.message, target.message);
985
+ }
986
+ function waitFor(callback, _ref) {
987
+ let {
988
+ container = getDocument(),
989
+ timeout = getConfig().asyncUtilTimeout,
990
+ showOriginalStackTrace = getConfig().showOriginalStackTrace,
991
+ stackTraceError,
992
+ interval = 50,
993
+ onTimeout = error => {
994
+ Object.defineProperty(error, 'message', {
995
+ value: getConfig().getElementError(error.message, container).message
996
+ });
997
+ return error;
998
+ },
999
+ mutationObserverOptions = {
1000
+ subtree: true,
1001
+ childList: true,
1002
+ attributes: true,
1003
+ characterData: true
1004
+ }
1005
+ } = _ref;
1006
+ if (typeof callback !== 'function') {
1007
+ throw new TypeError('Received `callback` arg must be a function');
1008
+ }
1009
+ return new Promise(async (resolve, reject) => {
1010
+ let lastError, intervalId, observer;
1011
+ let finished = false;
1012
+ let promiseStatus = 'idle';
1013
+ const overallTimeoutTimer = setTimeout(handleTimeout, timeout);
1014
+ const usingJestFakeTimers = jestFakeTimersAreEnabled();
1015
+ if (usingJestFakeTimers) {
1016
+ const {
1017
+ unstable_advanceTimersWrapper: advanceTimersWrapper
1018
+ } = getConfig();
1019
+ checkCallback();
1020
+ // this is a dangerous rule to disable because it could lead to an
1021
+ // infinite loop. However, eslint isn't smart enough to know that we're
1022
+ // setting finished inside `onDone` which will be called when we're done
1023
+ // waiting or when we've timed out.
1024
+ // eslint-disable-next-line no-unmodified-loop-condition
1025
+ while (!finished) {
1026
+ if (!jestFakeTimersAreEnabled()) {
1027
+ const error = new Error("Changed from using fake timers to real timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to real timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830");
1028
+ if (!showOriginalStackTrace) copyStackTrace(error, stackTraceError);
1029
+ reject(error);
1030
+ return;
1031
+ }
1032
+
1033
+ // In this rare case, we *need* to wait for in-flight promises
1034
+ // to resolve before continuing. We don't need to take advantage
1035
+ // of parallelization so we're fine.
1036
+ // https://stackoverflow.com/a/59243586/971592
1037
+ // eslint-disable-next-line no-await-in-loop
1038
+ await advanceTimersWrapper(async () => {
1039
+ // we *could* (maybe should?) use `advanceTimersToNextTimer` but it's
1040
+ // possible that could make this loop go on forever if someone is using
1041
+ // third party code that's setting up recursive timers so rapidly that
1042
+ // the user's timer's don't get a chance to resolve. So we'll advance
1043
+ // by an interval instead. (We have a test for this case).
1044
+ jest.advanceTimersByTime(interval);
1045
+ });
1046
+
1047
+ // Could have timed-out
1048
+ if (finished) {
1049
+ break;
1050
+ }
1051
+ // It's really important that checkCallback is run *before* we flush
1052
+ // in-flight promises. To be honest, I'm not sure why, and I can't quite
1053
+ // think of a way to reproduce the problem in a test, but I spent
1054
+ // an entire day banging my head against a wall on this.
1055
+ checkCallback();
1056
+ }
1057
+ } else {
1058
+ try {
1059
+ checkContainerType(container);
1060
+ } catch (e) {
1061
+ reject(e);
1062
+ return;
1063
+ }
1064
+ intervalId = setInterval(checkRealTimersCallback, interval);
1065
+ const {
1066
+ MutationObserver
1067
+ } = getWindowFromNode(container);
1068
+ observer = new MutationObserver(checkRealTimersCallback);
1069
+ observer.observe(container, mutationObserverOptions);
1070
+ checkCallback();
1071
+ }
1072
+ function onDone(error, result) {
1073
+ finished = true;
1074
+ clearTimeout(overallTimeoutTimer);
1075
+ if (!usingJestFakeTimers) {
1076
+ clearInterval(intervalId);
1077
+ observer.disconnect();
1078
+ }
1079
+ if (error) {
1080
+ reject(error);
1081
+ } else {
1082
+ resolve(result);
1083
+ }
1084
+ }
1085
+ function checkRealTimersCallback() {
1086
+ if (jestFakeTimersAreEnabled()) {
1087
+ const error = new Error("Changed from using real timers to fake timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to fake timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830");
1088
+ if (!showOriginalStackTrace) copyStackTrace(error, stackTraceError);
1089
+ return reject(error);
1090
+ } else {
1091
+ return checkCallback();
1092
+ }
1093
+ }
1094
+ function checkCallback() {
1095
+ if (promiseStatus === 'pending') return;
1096
+ try {
1097
+ const result = runWithExpensiveErrorDiagnosticsDisabled(callback);
1098
+ if (typeof (result == null ? void 0 : result.then) === 'function') {
1099
+ promiseStatus = 'pending';
1100
+ result.then(resolvedValue => {
1101
+ promiseStatus = 'resolved';
1102
+ onDone(null, resolvedValue);
1103
+ }, rejectedValue => {
1104
+ promiseStatus = 'rejected';
1105
+ lastError = rejectedValue;
1106
+ });
1107
+ } else {
1108
+ onDone(null, result);
1109
+ }
1110
+ // If `callback` throws, wait for the next mutation, interval, or timeout.
1111
+ } catch (error) {
1112
+ // Save the most recent callback error to reject the promise with it in the event of a timeout
1113
+ lastError = error;
1114
+ }
1115
+ }
1116
+ function handleTimeout() {
1117
+ let error;
1118
+ if (lastError) {
1119
+ error = lastError;
1120
+ if (!showOriginalStackTrace && error.name === 'TestingLibraryElementError') {
1121
+ copyStackTrace(error, stackTraceError);
1122
+ }
1123
+ } else {
1124
+ error = new Error('Timed out in waitFor.');
1125
+ if (!showOriginalStackTrace) {
1126
+ copyStackTrace(error, stackTraceError);
1127
+ }
1128
+ }
1129
+ onDone(onTimeout(error), null);
1130
+ }
1131
+ });
1132
+ }
1133
+ function waitForWrapper(callback, options) {
1134
+ // create the error here so its stack trace is as close to the
1135
+ // calling code as possible
1136
+ const stackTraceError = new Error('STACK_TRACE_MESSAGE');
1137
+ return getConfig().asyncWrapper(() => waitFor(callback, {
1138
+ stackTraceError,
1139
+ ...options
1140
+ }));
1141
+ }
1142
+
1143
+ /*
1144
+ eslint
1145
+ max-lines-per-function: ["error", {"max": 200}],
1146
+ */
1147
+
1148
+ function getElementError(message, container) {
1149
+ return getConfig().getElementError(message, container);
1150
+ }
1151
+ function getMultipleElementsFoundError(message, container) {
1152
+ return getElementError(message + "\n\n(If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).", container);
1153
+ }
1154
+ function queryAllByAttribute(attribute, container, text, _temp) {
1155
+ let {
1156
+ exact = true,
1157
+ collapseWhitespace,
1158
+ trim,
1159
+ normalizer
1160
+ } = _temp === void 0 ? {} : _temp;
1161
+ const matcher = exact ? matches : fuzzyMatches;
1162
+ const matchNormalizer = makeNormalizer({
1163
+ collapseWhitespace,
1164
+ trim,
1165
+ normalizer
1166
+ });
1167
+ return Array.from(container.querySelectorAll("[" + attribute + "]")).filter(node => matcher(node.getAttribute(attribute), node, text, matchNormalizer));
1168
+ }
1169
+ function queryByAttribute(attribute, container, text, options) {
1170
+ const els = queryAllByAttribute(attribute, container, text, options);
1171
+ if (els.length > 1) {
1172
+ throw getMultipleElementsFoundError("Found multiple elements by [" + attribute + "=" + text + "]", container);
1173
+ }
1174
+ return els[0] || null;
1175
+ }
1176
+
1177
+ // this accepts a query function and returns a function which throws an error
1178
+ // if more than one elements is returned, otherwise it returns the first
1179
+ // element or null
1180
+ function makeSingleQuery(allQuery, getMultipleError) {
1181
+ return function (container) {
1182
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1183
+ args[_key - 1] = arguments[_key];
1184
+ }
1185
+ const els = allQuery(container, ...args);
1186
+ if (els.length > 1) {
1187
+ const elementStrings = els.map(element => getElementError(null, element).message).join('\n\n');
1188
+ throw getMultipleElementsFoundError(getMultipleError(container, ...args) + "\n\nHere are the matching elements:\n\n" + elementStrings, container);
1189
+ }
1190
+ return els[0] || null;
1191
+ };
1192
+ }
1193
+ function getSuggestionError(suggestion, container) {
1194
+ return getConfig().getElementError("A better query is available, try this:\n" + suggestion.toString() + "\n", container);
1195
+ }
1196
+
1197
+ // this accepts a query function and returns a function which throws an error
1198
+ // if an empty list of elements is returned
1199
+ function makeGetAllQuery(allQuery, getMissingError) {
1200
+ return function (container) {
1201
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
1202
+ args[_key2 - 1] = arguments[_key2];
1203
+ }
1204
+ const els = allQuery(container, ...args);
1205
+ if (!els.length) {
1206
+ throw getConfig().getElementError(getMissingError(container, ...args), container);
1207
+ }
1208
+ return els;
1209
+ };
1210
+ }
1211
+
1212
+ // this accepts a getter query function and returns a function which calls
1213
+ // waitFor and passing a function which invokes the getter.
1214
+ function makeFindQuery(getter) {
1215
+ return (container, text, options, waitForOptions) => {
1216
+ return waitForWrapper(() => {
1217
+ return getter(container, text, options);
1218
+ }, {
1219
+ container,
1220
+ ...waitForOptions
1221
+ });
1222
+ };
1223
+ }
1224
+ const wrapSingleQueryWithSuggestion = (query, queryAllByName, variant) => function (container) {
1225
+ for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
1226
+ args[_key3 - 1] = arguments[_key3];
1227
+ }
1228
+ const element = query(container, ...args);
1229
+ const [{
1230
+ suggest = getConfig().throwSuggestions
1231
+ } = {}] = args.slice(-1);
1232
+ if (element && suggest) {
1233
+ const suggestion = getSuggestedQuery(element, variant);
1234
+ if (suggestion && !queryAllByName.endsWith(suggestion.queryName)) {
1235
+ throw getSuggestionError(suggestion.toString(), container);
1236
+ }
1237
+ }
1238
+ return element;
1239
+ };
1240
+ const wrapAllByQueryWithSuggestion = (query, queryAllByName, variant) => function (container) {
1241
+ for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
1242
+ args[_key4 - 1] = arguments[_key4];
1243
+ }
1244
+ const els = query(container, ...args);
1245
+ const [{
1246
+ suggest = getConfig().throwSuggestions
1247
+ } = {}] = args.slice(-1);
1248
+ if (els.length && suggest) {
1249
+ // get a unique list of all suggestion messages. We are only going to make a suggestion if
1250
+ // all the suggestions are the same
1251
+ const uniqueSuggestionMessages = [...new Set(els.map(element => {
1252
+ var _getSuggestedQuery;
1253
+ return (_getSuggestedQuery = getSuggestedQuery(element, variant)) == null ? void 0 : _getSuggestedQuery.toString();
1254
+ }))];
1255
+ if (
1256
+ // only want to suggest if all the els have the same suggestion.
1257
+ uniqueSuggestionMessages.length === 1 && !queryAllByName.endsWith(
1258
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- TODO: Can this be null at runtime?
1259
+ getSuggestedQuery(els[0], variant).queryName)) {
1260
+ throw getSuggestionError(uniqueSuggestionMessages[0], container);
1261
+ }
1262
+ }
1263
+ return els;
1264
+ };
1265
+
1266
+ // TODO: This deviates from the published declarations
1267
+ // However, the implementation always required a dyadic (after `container`) not variadic `queryAllBy` considering the implementation of `makeFindQuery`
1268
+ // This is at least statically true and can be verified by accepting `QueryMethod<Arguments, HTMLElement[]>`
1269
+ function buildQueries(queryAllBy, getMultipleError, getMissingError) {
1270
+ const queryBy = wrapSingleQueryWithSuggestion(makeSingleQuery(queryAllBy, getMultipleError), queryAllBy.name, 'query');
1271
+ const getAllBy = makeGetAllQuery(queryAllBy, getMissingError);
1272
+ const getBy = makeSingleQuery(getAllBy, getMultipleError);
1273
+ const getByWithSuggestions = wrapSingleQueryWithSuggestion(getBy, queryAllBy.name, 'get');
1274
+ const getAllWithSuggestions = wrapAllByQueryWithSuggestion(getAllBy, queryAllBy.name.replace('query', 'get'), 'getAll');
1275
+ const findAllBy = makeFindQuery(wrapAllByQueryWithSuggestion(getAllBy, queryAllBy.name, 'findAll'));
1276
+ const findBy = makeFindQuery(wrapSingleQueryWithSuggestion(getBy, queryAllBy.name, 'find'));
1277
+ return [queryBy, getAllWithSuggestions, getByWithSuggestions, findAllBy, findBy];
1278
+ }
1279
+
1280
+ var queryHelpers = /*#__PURE__*/Object.freeze({
1281
+ __proto__: null,
1282
+ getElementError: getElementError,
1283
+ wrapAllByQueryWithSuggestion: wrapAllByQueryWithSuggestion,
1284
+ wrapSingleQueryWithSuggestion: wrapSingleQueryWithSuggestion,
1285
+ getMultipleElementsFoundError: getMultipleElementsFoundError,
1286
+ queryAllByAttribute: queryAllByAttribute,
1287
+ queryByAttribute: queryByAttribute,
1288
+ makeSingleQuery: makeSingleQuery,
1289
+ makeGetAllQuery: makeGetAllQuery,
1290
+ makeFindQuery: makeFindQuery,
1291
+ buildQueries: buildQueries
1292
+ });
1293
+
1294
+ function queryAllLabels(container) {
1295
+ return Array.from(container.querySelectorAll('label,input')).map(node => {
1296
+ return {
1297
+ node,
1298
+ textToMatch: getLabelContent(node)
1299
+ };
1300
+ }).filter(_ref => {
1301
+ let {
1302
+ textToMatch
1303
+ } = _ref;
1304
+ return textToMatch !== null;
1305
+ });
1306
+ }
1307
+ const queryAllLabelsByText = function (container, text, _temp) {
1308
+ let {
1309
+ exact = true,
1310
+ trim,
1311
+ collapseWhitespace,
1312
+ normalizer
1313
+ } = _temp === void 0 ? {} : _temp;
1314
+ const matcher = exact ? matches : fuzzyMatches;
1315
+ const matchNormalizer = makeNormalizer({
1316
+ collapseWhitespace,
1317
+ trim,
1318
+ normalizer
1319
+ });
1320
+ const textToMatchByLabels = queryAllLabels(container);
1321
+ return textToMatchByLabels.filter(_ref2 => {
1322
+ let {
1323
+ node,
1324
+ textToMatch
1325
+ } = _ref2;
1326
+ return matcher(textToMatch, node, text, matchNormalizer);
1327
+ }).map(_ref3 => {
1328
+ let {
1329
+ node
1330
+ } = _ref3;
1331
+ return node;
1332
+ });
1333
+ };
1334
+ const queryAllByLabelText = function (container, text, _temp2) {
1335
+ let {
1336
+ selector = '*',
1337
+ exact = true,
1338
+ collapseWhitespace,
1339
+ trim,
1340
+ normalizer
1341
+ } = _temp2 === void 0 ? {} : _temp2;
1342
+ checkContainerType(container);
1343
+ const matcher = exact ? matches : fuzzyMatches;
1344
+ const matchNormalizer = makeNormalizer({
1345
+ collapseWhitespace,
1346
+ trim,
1347
+ normalizer
1348
+ });
1349
+ const matchingLabelledElements = Array.from(container.querySelectorAll('*')).filter(element => {
1350
+ return getRealLabels(element).length || element.hasAttribute('aria-labelledby');
1351
+ }).reduce((labelledElements, labelledElement) => {
1352
+ const labelList = getLabels(container, labelledElement, {
1353
+ selector
1354
+ });
1355
+ labelList.filter(label => Boolean(label.formControl)).forEach(label => {
1356
+ if (matcher(label.content, label.formControl, text, matchNormalizer) && label.formControl) {
1357
+ labelledElements.push(label.formControl);
1358
+ }
1359
+ });
1360
+ const labelsValue = labelList.filter(label => Boolean(label.content)).map(label => label.content);
1361
+ if (matcher(labelsValue.join(' '), labelledElement, text, matchNormalizer)) {
1362
+ labelledElements.push(labelledElement);
1363
+ }
1364
+ if (labelsValue.length > 1) {
1365
+ labelsValue.forEach((labelValue, index) => {
1366
+ if (matcher(labelValue, labelledElement, text, matchNormalizer)) {
1367
+ labelledElements.push(labelledElement);
1368
+ }
1369
+ const labelsFiltered = [...labelsValue];
1370
+ labelsFiltered.splice(index, 1);
1371
+ if (labelsFiltered.length > 1) {
1372
+ if (matcher(labelsFiltered.join(' '), labelledElement, text, matchNormalizer)) {
1373
+ labelledElements.push(labelledElement);
1374
+ }
1375
+ }
1376
+ });
1377
+ }
1378
+ return labelledElements;
1379
+ }, []).concat(queryAllByAttribute('aria-label', container, text, {
1380
+ exact,
1381
+ normalizer: matchNormalizer
1382
+ }));
1383
+ return Array.from(new Set(matchingLabelledElements)).filter(element => element.matches(selector));
1384
+ };
1385
+
1386
+ // the getAll* query would normally look like this:
1387
+ // const getAllByLabelText = makeGetAllQuery(
1388
+ // queryAllByLabelText,
1389
+ // (c, text) => `Unable to find a label with the text of: ${text}`,
1390
+ // )
1391
+ // however, we can give a more helpful error message than the generic one,
1392
+ // so we're writing this one out by hand.
1393
+ const getAllByLabelText = function (container, text) {
1394
+ for (var _len = arguments.length, rest = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
1395
+ rest[_key - 2] = arguments[_key];
1396
+ }
1397
+ const els = queryAllByLabelText(container, text, ...rest);
1398
+ if (!els.length) {
1399
+ const labels = queryAllLabelsByText(container, text, ...rest);
1400
+ if (labels.length) {
1401
+ const tagNames = labels.map(label => getTagNameOfElementAssociatedWithLabelViaFor(container, label)).filter(tagName => !!tagName);
1402
+ if (tagNames.length) {
1403
+ throw getConfig().getElementError(tagNames.map(tagName => "Found a label with the text of: " + text + ", however the element associated with this label (<" + tagName + " />) is non-labellable [https://html.spec.whatwg.org/multipage/forms.html#category-label]. If you really need to label a <" + tagName + " />, you can use aria-label or aria-labelledby instead.").join('\n\n'), container);
1404
+ } else {
1405
+ throw getConfig().getElementError("Found a label with the text of: " + text + ", however no form control was found associated to that label. Make sure you're using the \"for\" attribute or \"aria-labelledby\" attribute correctly.", container);
1406
+ }
1407
+ } else {
1408
+ throw getConfig().getElementError("Unable to find a label with the text of: " + text, container);
1409
+ }
1410
+ }
1411
+ return els;
1412
+ };
1413
+ function getTagNameOfElementAssociatedWithLabelViaFor(container, label) {
1414
+ const htmlFor = label.getAttribute('for');
1415
+ if (!htmlFor) {
1416
+ return null;
1417
+ }
1418
+ const element = container.querySelector("[id=\"" + htmlFor + "\"]");
1419
+ return element ? element.tagName.toLowerCase() : null;
1420
+ }
1421
+
1422
+ // the reason mentioned above is the same reason we're not using buildQueries
1423
+ const getMultipleError$7 = (c, text) => "Found multiple elements with the text of: " + text;
1424
+ const queryByLabelText = wrapSingleQueryWithSuggestion(makeSingleQuery(queryAllByLabelText, getMultipleError$7), queryAllByLabelText.name, 'query');
1425
+ const getByLabelText = makeSingleQuery(getAllByLabelText, getMultipleError$7);
1426
+ const findAllByLabelText = makeFindQuery(wrapAllByQueryWithSuggestion(getAllByLabelText, getAllByLabelText.name, 'findAll'));
1427
+ const findByLabelText = makeFindQuery(wrapSingleQueryWithSuggestion(getByLabelText, getAllByLabelText.name, 'find'));
1428
+ const getAllByLabelTextWithSuggestions = wrapAllByQueryWithSuggestion(getAllByLabelText, getAllByLabelText.name, 'getAll');
1429
+ const getByLabelTextWithSuggestions = wrapSingleQueryWithSuggestion(getByLabelText, getAllByLabelText.name, 'get');
1430
+ const queryAllByLabelTextWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByLabelText, queryAllByLabelText.name, 'queryAll');
1431
+
1432
+ const queryAllByPlaceholderText = function () {
1433
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1434
+ args[_key] = arguments[_key];
1435
+ }
1436
+ checkContainerType(args[0]);
1437
+ return queryAllByAttribute('placeholder', ...args);
1438
+ };
1439
+ const getMultipleError$6 = (c, text) => "Found multiple elements with the placeholder text of: " + text;
1440
+ const getMissingError$6 = (c, text) => "Unable to find an element with the placeholder text of: " + text;
1441
+ const queryAllByPlaceholderTextWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByPlaceholderText, queryAllByPlaceholderText.name, 'queryAll');
1442
+ const [queryByPlaceholderText, getAllByPlaceholderText, getByPlaceholderText, findAllByPlaceholderText, findByPlaceholderText] = buildQueries(queryAllByPlaceholderText, getMultipleError$6, getMissingError$6);
1443
+
1444
+ const queryAllByText = function (container, text, _temp) {
1445
+ let {
1446
+ selector = '*',
1447
+ exact = true,
1448
+ collapseWhitespace,
1449
+ trim,
1450
+ ignore = getConfig().defaultIgnore,
1451
+ normalizer
1452
+ } = _temp === void 0 ? {} : _temp;
1453
+ checkContainerType(container);
1454
+ const matcher = exact ? matches : fuzzyMatches;
1455
+ const matchNormalizer = makeNormalizer({
1456
+ collapseWhitespace,
1457
+ trim,
1458
+ normalizer
1459
+ });
1460
+ let baseArray = [];
1461
+ if (typeof container.matches === 'function' && container.matches(selector)) {
1462
+ baseArray = [container];
1463
+ }
1464
+ return [...baseArray, ...Array.from(container.querySelectorAll(selector))]
1465
+ // TODO: `matches` according lib.dom.d.ts can get only `string` but according our code it can handle also boolean :)
1466
+ .filter(node => !ignore || !node.matches(ignore)).filter(node => matcher(getNodeText(node), node, text, matchNormalizer));
1467
+ };
1468
+ const getMultipleError$5 = (c, text) => "Found multiple elements with the text: " + text;
1469
+ const getMissingError$5 = function (c, text, options) {
1470
+ if (options === void 0) {
1471
+ options = {};
1472
+ }
1473
+ const {
1474
+ collapseWhitespace,
1475
+ trim,
1476
+ normalizer,
1477
+ selector
1478
+ } = options;
1479
+ const matchNormalizer = makeNormalizer({
1480
+ collapseWhitespace,
1481
+ trim,
1482
+ normalizer
1483
+ });
1484
+ const normalizedText = matchNormalizer(text.toString());
1485
+ const isNormalizedDifferent = normalizedText !== text.toString();
1486
+ const isCustomSelector = (selector != null ? selector : '*') !== '*';
1487
+ return "Unable to find an element with the text: " + (isNormalizedDifferent ? normalizedText + " (normalized from '" + text + "')" : text) + (isCustomSelector ? ", which matches selector '" + selector + "'" : '') + ". This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.";
1488
+ };
1489
+ const queryAllByTextWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByText, queryAllByText.name, 'queryAll');
1490
+ const [queryByText, getAllByText, getByText, findAllByText, findByText] = buildQueries(queryAllByText, getMultipleError$5, getMissingError$5);
1491
+
1492
+ const queryAllByDisplayValue = function (container, value, _temp) {
1493
+ let {
1494
+ exact = true,
1495
+ collapseWhitespace,
1496
+ trim,
1497
+ normalizer
1498
+ } = _temp === void 0 ? {} : _temp;
1499
+ checkContainerType(container);
1500
+ const matcher = exact ? matches : fuzzyMatches;
1501
+ const matchNormalizer = makeNormalizer({
1502
+ collapseWhitespace,
1503
+ trim,
1504
+ normalizer
1505
+ });
1506
+ return Array.from(container.querySelectorAll("input,textarea,select")).filter(node => {
1507
+ if (node.tagName === 'SELECT') {
1508
+ const selectedOptions = Array.from(node.options).filter(option => option.selected);
1509
+ return selectedOptions.some(optionNode => matcher(getNodeText(optionNode), optionNode, value, matchNormalizer));
1510
+ } else {
1511
+ return matcher(node.value, node, value, matchNormalizer);
1512
+ }
1513
+ });
1514
+ };
1515
+ const getMultipleError$4 = (c, value) => "Found multiple elements with the display value: " + value + ".";
1516
+ const getMissingError$4 = (c, value) => "Unable to find an element with the display value: " + value + ".";
1517
+ const queryAllByDisplayValueWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByDisplayValue, queryAllByDisplayValue.name, 'queryAll');
1518
+ const [queryByDisplayValue, getAllByDisplayValue, getByDisplayValue, findAllByDisplayValue, findByDisplayValue] = buildQueries(queryAllByDisplayValue, getMultipleError$4, getMissingError$4);
1519
+
1520
+ // Valid tags are img, input, area and custom elements
1521
+ const VALID_TAG_REGEXP = /^(img|input|area|.+-.+)$/i;
1522
+ const queryAllByAltText = function (container, alt, options) {
1523
+ if (options === void 0) {
1524
+ options = {};
1525
+ }
1526
+ checkContainerType(container);
1527
+ return queryAllByAttribute('alt', container, alt, options).filter(node => VALID_TAG_REGEXP.test(node.tagName));
1528
+ };
1529
+ const getMultipleError$3 = (c, alt) => "Found multiple elements with the alt text: " + alt;
1530
+ const getMissingError$3 = (c, alt) => "Unable to find an element with the alt text: " + alt;
1531
+ const queryAllByAltTextWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByAltText, queryAllByAltText.name, 'queryAll');
1532
+ const [queryByAltText, getAllByAltText, getByAltText, findAllByAltText, findByAltText] = buildQueries(queryAllByAltText, getMultipleError$3, getMissingError$3);
1533
+
1534
+ const isSvgTitle = node => {
1535
+ var _node$parentElement;
1536
+ return node.tagName.toLowerCase() === 'title' && ((_node$parentElement = node.parentElement) == null ? void 0 : _node$parentElement.tagName.toLowerCase()) === 'svg';
1537
+ };
1538
+ const queryAllByTitle = function (container, text, _temp) {
1539
+ let {
1540
+ exact = true,
1541
+ collapseWhitespace,
1542
+ trim,
1543
+ normalizer
1544
+ } = _temp === void 0 ? {} : _temp;
1545
+ checkContainerType(container);
1546
+ const matcher = exact ? matches : fuzzyMatches;
1547
+ const matchNormalizer = makeNormalizer({
1548
+ collapseWhitespace,
1549
+ trim,
1550
+ normalizer
1551
+ });
1552
+ return Array.from(container.querySelectorAll('[title], svg > title')).filter(node => matcher(node.getAttribute('title'), node, text, matchNormalizer) || isSvgTitle(node) && matcher(getNodeText(node), node, text, matchNormalizer));
1553
+ };
1554
+ const getMultipleError$2 = (c, title) => "Found multiple elements with the title: " + title + ".";
1555
+ const getMissingError$2 = (c, title) => "Unable to find an element with the title: " + title + ".";
1556
+ const queryAllByTitleWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByTitle, queryAllByTitle.name, 'queryAll');
1557
+ const [queryByTitle, getAllByTitle, getByTitle, findAllByTitle, findByTitle] = buildQueries(queryAllByTitle, getMultipleError$2, getMissingError$2);
1558
+
1559
+ /* eslint-disable complexity */
1560
+ const queryAllByRole = function (container, role, _temp) {
1561
+ let {
1562
+ hidden = getConfig().defaultHidden,
1563
+ name,
1564
+ description,
1565
+ queryFallbacks = false,
1566
+ selected,
1567
+ busy,
1568
+ checked,
1569
+ pressed,
1570
+ current,
1571
+ level,
1572
+ expanded,
1573
+ value: {
1574
+ now: valueNow,
1575
+ min: valueMin,
1576
+ max: valueMax,
1577
+ text: valueText
1578
+ } = {}
1579
+ } = _temp === void 0 ? {} : _temp;
1580
+ checkContainerType(container);
1581
+ if (selected !== undefined) {
1582
+ var _allRoles$get;
1583
+ // guard against unknown roles
1584
+ if (((_allRoles$get = roles.get(role)) == null ? void 0 : _allRoles$get.props['aria-selected']) === undefined) {
1585
+ throw new Error("\"aria-selected\" is not supported on role \"" + role + "\".");
1586
+ }
1587
+ }
1588
+ if (busy !== undefined) {
1589
+ var _allRoles$get2;
1590
+ // guard against unknown roles
1591
+ if (((_allRoles$get2 = roles.get(role)) == null ? void 0 : _allRoles$get2.props['aria-busy']) === undefined) {
1592
+ throw new Error("\"aria-busy\" is not supported on role \"" + role + "\".");
1593
+ }
1594
+ }
1595
+ if (checked !== undefined) {
1596
+ var _allRoles$get3;
1597
+ // guard against unknown roles
1598
+ if (((_allRoles$get3 = roles.get(role)) == null ? void 0 : _allRoles$get3.props['aria-checked']) === undefined) {
1599
+ throw new Error("\"aria-checked\" is not supported on role \"" + role + "\".");
1600
+ }
1601
+ }
1602
+ if (pressed !== undefined) {
1603
+ var _allRoles$get4;
1604
+ // guard against unknown roles
1605
+ if (((_allRoles$get4 = roles.get(role)) == null ? void 0 : _allRoles$get4.props['aria-pressed']) === undefined) {
1606
+ throw new Error("\"aria-pressed\" is not supported on role \"" + role + "\".");
1607
+ }
1608
+ }
1609
+ if (current !== undefined) {
1610
+ var _allRoles$get5;
1611
+ /* istanbul ignore next */
1612
+ // guard against unknown roles
1613
+ // All currently released ARIA versions support `aria-current` on all roles.
1614
+ // Leaving this for symmetry and forward compatibility
1615
+ if (((_allRoles$get5 = roles.get(role)) == null ? void 0 : _allRoles$get5.props['aria-current']) === undefined) {
1616
+ throw new Error("\"aria-current\" is not supported on role \"" + role + "\".");
1617
+ }
1618
+ }
1619
+ if (level !== undefined) {
1620
+ // guard against using `level` option with any role other than `heading`
1621
+ if (role !== 'heading') {
1622
+ throw new Error("Role \"" + role + "\" cannot have \"level\" property.");
1623
+ }
1624
+ }
1625
+ if (valueNow !== undefined) {
1626
+ var _allRoles$get6;
1627
+ // guard against unknown roles
1628
+ if (((_allRoles$get6 = roles.get(role)) == null ? void 0 : _allRoles$get6.props['aria-valuenow']) === undefined) {
1629
+ throw new Error("\"aria-valuenow\" is not supported on role \"" + role + "\".");
1630
+ }
1631
+ }
1632
+ if (valueMax !== undefined) {
1633
+ var _allRoles$get7;
1634
+ // guard against unknown roles
1635
+ if (((_allRoles$get7 = roles.get(role)) == null ? void 0 : _allRoles$get7.props['aria-valuemax']) === undefined) {
1636
+ throw new Error("\"aria-valuemax\" is not supported on role \"" + role + "\".");
1637
+ }
1638
+ }
1639
+ if (valueMin !== undefined) {
1640
+ var _allRoles$get8;
1641
+ // guard against unknown roles
1642
+ if (((_allRoles$get8 = roles.get(role)) == null ? void 0 : _allRoles$get8.props['aria-valuemin']) === undefined) {
1643
+ throw new Error("\"aria-valuemin\" is not supported on role \"" + role + "\".");
1644
+ }
1645
+ }
1646
+ if (valueText !== undefined) {
1647
+ var _allRoles$get9;
1648
+ // guard against unknown roles
1649
+ if (((_allRoles$get9 = roles.get(role)) == null ? void 0 : _allRoles$get9.props['aria-valuetext']) === undefined) {
1650
+ throw new Error("\"aria-valuetext\" is not supported on role \"" + role + "\".");
1651
+ }
1652
+ }
1653
+ if (expanded !== undefined) {
1654
+ var _allRoles$get0;
1655
+ // guard against unknown roles
1656
+ if (((_allRoles$get0 = roles.get(role)) == null ? void 0 : _allRoles$get0.props['aria-expanded']) === undefined) {
1657
+ throw new Error("\"aria-expanded\" is not supported on role \"" + role + "\".");
1658
+ }
1659
+ }
1660
+ const subtreeIsInaccessibleCache = new WeakMap();
1661
+ function cachedIsSubtreeInaccessible(element) {
1662
+ if (!subtreeIsInaccessibleCache.has(element)) {
1663
+ subtreeIsInaccessibleCache.set(element, isSubtreeInaccessible(element));
1664
+ }
1665
+ return subtreeIsInaccessibleCache.get(element);
1666
+ }
1667
+ return Array.from(container.querySelectorAll(
1668
+ // Only query elements that can be matched by the following filters
1669
+ makeRoleSelector(role))).filter(node => {
1670
+ const isRoleSpecifiedExplicitly = node.hasAttribute('role');
1671
+ if (isRoleSpecifiedExplicitly) {
1672
+ const roleValue = node.getAttribute('role');
1673
+ if (queryFallbacks) {
1674
+ return roleValue.split(' ').filter(Boolean).some(roleAttributeToken => roleAttributeToken === role);
1675
+ }
1676
+ // other wise only send the first token to match
1677
+ const [firstRoleAttributeToken] = roleValue.split(' ');
1678
+ return firstRoleAttributeToken === role;
1679
+ }
1680
+ const implicitRoles = getImplicitAriaRoles(node);
1681
+ return implicitRoles.some(implicitRole => {
1682
+ return implicitRole === role;
1683
+ });
1684
+ }).filter(element => {
1685
+ if (selected !== undefined) {
1686
+ return selected === computeAriaSelected(element);
1687
+ }
1688
+ if (busy !== undefined) {
1689
+ return busy === computeAriaBusy(element);
1690
+ }
1691
+ if (checked !== undefined) {
1692
+ return checked === computeAriaChecked(element);
1693
+ }
1694
+ if (pressed !== undefined) {
1695
+ return pressed === computeAriaPressed(element);
1696
+ }
1697
+ if (current !== undefined) {
1698
+ return current === computeAriaCurrent(element);
1699
+ }
1700
+ if (expanded !== undefined) {
1701
+ return expanded === computeAriaExpanded(element);
1702
+ }
1703
+ if (level !== undefined) {
1704
+ return level === computeHeadingLevel(element);
1705
+ }
1706
+ if (valueNow !== undefined || valueMax !== undefined || valueMin !== undefined || valueText !== undefined) {
1707
+ let valueMatches = true;
1708
+ if (valueNow !== undefined) {
1709
+ valueMatches && (valueMatches = valueNow === computeAriaValueNow(element));
1710
+ }
1711
+ if (valueMax !== undefined) {
1712
+ valueMatches && (valueMatches = valueMax === computeAriaValueMax(element));
1713
+ }
1714
+ if (valueMin !== undefined) {
1715
+ valueMatches && (valueMatches = valueMin === computeAriaValueMin(element));
1716
+ }
1717
+ if (valueText !== undefined) {
1718
+ var _computeAriaValueText;
1719
+ valueMatches && (valueMatches = matches((_computeAriaValueText = computeAriaValueText(element)) != null ? _computeAriaValueText : null, element, valueText, text => text));
1720
+ }
1721
+ return valueMatches;
1722
+ }
1723
+ // don't care if aria attributes are unspecified
1724
+ return true;
1725
+ }).filter(element => {
1726
+ if (name === undefined) {
1727
+ // Don't care
1728
+ return true;
1729
+ }
1730
+ return matches(computeAccessibleName(element, {
1731
+ computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
1732
+ }), element, name, text => text);
1733
+ }).filter(element => {
1734
+ if (description === undefined) {
1735
+ // Don't care
1736
+ return true;
1737
+ }
1738
+ return matches(computeAccessibleDescription(element, {
1739
+ computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
1740
+ }), element, description, text => text);
1741
+ }).filter(element => {
1742
+ return hidden === false ? isInaccessible(element, {
1743
+ isSubtreeInaccessible: cachedIsSubtreeInaccessible
1744
+ }) === false : true;
1745
+ });
1746
+ };
1747
+ function makeRoleSelector(role) {
1748
+ var _roleElements$get;
1749
+ const explicitRoleSelector = "*[role~=\"" + role + "\"]";
1750
+ const roleRelations = (_roleElements$get = roleElements.get(role)) != null ? _roleElements$get : new Set();
1751
+ const implicitRoleSelectors = new Set(Array.from(roleRelations).map(_ref => {
1752
+ let {
1753
+ name
1754
+ } = _ref;
1755
+ return name;
1756
+ }));
1757
+
1758
+ // Current transpilation config sometimes assumes `...` is always applied to arrays.
1759
+ // `...` is equivalent to `Array.prototype.concat` for arrays.
1760
+ // If you replace this code with `[explicitRoleSelector, ...implicitRoleSelectors]`, make sure every transpilation target retains the `...` in favor of `Array.prototype.concat`.
1761
+ return [explicitRoleSelector].concat(Array.from(implicitRoleSelectors)).join(',');
1762
+ }
1763
+ const getNameHint = name => {
1764
+ let nameHint = '';
1765
+ if (name === undefined) {
1766
+ nameHint = '';
1767
+ } else if (typeof name === 'string') {
1768
+ nameHint = " and name \"" + name + "\"";
1769
+ } else {
1770
+ nameHint = " and name `" + name + "`";
1771
+ }
1772
+ return nameHint;
1773
+ };
1774
+ const getMultipleError$1 = function (c, role, _temp2) {
1775
+ let {
1776
+ name
1777
+ } = _temp2 === void 0 ? {} : _temp2;
1778
+ return "Found multiple elements with the role \"" + role + "\"" + getNameHint(name);
1779
+ };
1780
+ const getMissingError$1 = function (container, role, _temp3) {
1781
+ let {
1782
+ hidden = getConfig().defaultHidden,
1783
+ name,
1784
+ description
1785
+ } = _temp3 === void 0 ? {} : _temp3;
1786
+ if (getConfig()._disableExpensiveErrorDiagnostics) {
1787
+ return "Unable to find role=\"" + role + "\"" + getNameHint(name);
1788
+ }
1789
+ let roles = '';
1790
+ Array.from(container.children).forEach(childElement => {
1791
+ roles += prettyRoles(childElement, {
1792
+ hidden,
1793
+ includeDescription: description !== undefined
1794
+ });
1795
+ });
1796
+ let roleMessage;
1797
+ if (roles.length === 0) {
1798
+ if (hidden === false) {
1799
+ roleMessage = 'There are no accessible roles. But there might be some inaccessible roles. ' + 'If you wish to access them, then set the `hidden` option to `true`. ' + 'Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole';
1800
+ } else {
1801
+ roleMessage = 'There are no available roles.';
1802
+ }
1803
+ } else {
1804
+ roleMessage = ("\nHere are the " + (hidden === false ? 'accessible' : 'available') + " roles:\n\n " + roles.replace(/\n/g, '\n ').replace(/\n\s\s\n/g, '\n\n') + "\n").trim();
1805
+ }
1806
+ let nameHint = '';
1807
+ if (name === undefined) {
1808
+ nameHint = '';
1809
+ } else if (typeof name === 'string') {
1810
+ nameHint = " and name \"" + name + "\"";
1811
+ } else {
1812
+ nameHint = " and name `" + name + "`";
1813
+ }
1814
+ let descriptionHint = '';
1815
+ if (description === undefined) {
1816
+ descriptionHint = '';
1817
+ } else if (typeof description === 'string') {
1818
+ descriptionHint = " and description \"" + description + "\"";
1819
+ } else {
1820
+ descriptionHint = " and description `" + description + "`";
1821
+ }
1822
+ return ("\nUnable to find an " + (hidden === false ? 'accessible ' : '') + "element with the role \"" + role + "\"" + nameHint + descriptionHint + "\n\n" + roleMessage).trim();
1823
+ };
1824
+ const queryAllByRoleWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByRole, queryAllByRole.name, 'queryAll');
1825
+ const [queryByRole, getAllByRole, getByRole, findAllByRole, findByRole] = buildQueries(queryAllByRole, getMultipleError$1, getMissingError$1);
1826
+
1827
+ const getTestIdAttribute = () => getConfig().testIdAttribute;
1828
+ const queryAllByTestId = function () {
1829
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1830
+ args[_key] = arguments[_key];
1831
+ }
1832
+ checkContainerType(args[0]);
1833
+ return queryAllByAttribute(getTestIdAttribute(), ...args);
1834
+ };
1835
+ const getMultipleError = (c, id) => "Found multiple elements by: [" + getTestIdAttribute() + "=\"" + id + "\"]";
1836
+ const getMissingError = (c, id) => "Unable to find an element by: [" + getTestIdAttribute() + "=\"" + id + "\"]";
1837
+ const queryAllByTestIdWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByTestId, queryAllByTestId.name, 'queryAll');
1838
+ const [queryByTestId, getAllByTestId, getByTestId, findAllByTestId, findByTestId] = buildQueries(queryAllByTestId, getMultipleError, getMissingError);
1839
+
1840
+ var queries = /*#__PURE__*/Object.freeze({
1841
+ __proto__: null,
1842
+ queryAllByLabelText: queryAllByLabelTextWithSuggestions,
1843
+ queryByLabelText: queryByLabelText,
1844
+ getAllByLabelText: getAllByLabelTextWithSuggestions,
1845
+ getByLabelText: getByLabelTextWithSuggestions,
1846
+ findAllByLabelText: findAllByLabelText,
1847
+ findByLabelText: findByLabelText,
1848
+ queryByPlaceholderText: queryByPlaceholderText,
1849
+ queryAllByPlaceholderText: queryAllByPlaceholderTextWithSuggestions,
1850
+ getByPlaceholderText: getByPlaceholderText,
1851
+ getAllByPlaceholderText: getAllByPlaceholderText,
1852
+ findAllByPlaceholderText: findAllByPlaceholderText,
1853
+ findByPlaceholderText: findByPlaceholderText,
1854
+ queryByText: queryByText,
1855
+ queryAllByText: queryAllByTextWithSuggestions,
1856
+ getByText: getByText,
1857
+ getAllByText: getAllByText,
1858
+ findAllByText: findAllByText,
1859
+ findByText: findByText,
1860
+ queryByDisplayValue: queryByDisplayValue,
1861
+ queryAllByDisplayValue: queryAllByDisplayValueWithSuggestions,
1862
+ getByDisplayValue: getByDisplayValue,
1863
+ getAllByDisplayValue: getAllByDisplayValue,
1864
+ findAllByDisplayValue: findAllByDisplayValue,
1865
+ findByDisplayValue: findByDisplayValue,
1866
+ queryByAltText: queryByAltText,
1867
+ queryAllByAltText: queryAllByAltTextWithSuggestions,
1868
+ getByAltText: getByAltText,
1869
+ getAllByAltText: getAllByAltText,
1870
+ findAllByAltText: findAllByAltText,
1871
+ findByAltText: findByAltText,
1872
+ queryByTitle: queryByTitle,
1873
+ queryAllByTitle: queryAllByTitleWithSuggestions,
1874
+ getByTitle: getByTitle,
1875
+ getAllByTitle: getAllByTitle,
1876
+ findAllByTitle: findAllByTitle,
1877
+ findByTitle: findByTitle,
1878
+ queryByRole: queryByRole,
1879
+ queryAllByRole: queryAllByRoleWithSuggestions,
1880
+ getAllByRole: getAllByRole,
1881
+ getByRole: getByRole,
1882
+ findAllByRole: findAllByRole,
1883
+ findByRole: findByRole,
1884
+ queryByTestId: queryByTestId,
1885
+ queryAllByTestId: queryAllByTestIdWithSuggestions,
1886
+ getByTestId: getByTestId,
1887
+ getAllByTestId: getAllByTestId,
1888
+ findAllByTestId: findAllByTestId,
1889
+ findByTestId: findByTestId
1890
+ });
1891
+
1892
+ /**
1893
+ * @typedef {{[key: string]: Function}} FuncMap
1894
+ */
1895
+
1896
+ /**
1897
+ * @param {HTMLElement} element container
1898
+ * @param {FuncMap} queries object of functions
1899
+ * @param {Object} initialValue for reducer
1900
+ * @returns {FuncMap} returns object of functions bound to container
1901
+ */
1902
+ function getQueriesForElement(element, queries$1, initialValue) {
1903
+ if (queries$1 === void 0) {
1904
+ queries$1 = queries;
1905
+ }
1906
+ if (initialValue === void 0) {
1907
+ initialValue = {};
1908
+ }
1909
+ return Object.keys(queries$1).reduce((helpers, key) => {
1910
+ const fn = queries$1[key];
1911
+ helpers[key] = fn.bind(null, element);
1912
+ return helpers;
1913
+ }, initialValue);
1914
+ }
1915
+
1916
+ const isRemoved = result => !result || Array.isArray(result) && !result.length;
1917
+
1918
+ // Check if the element is not present.
1919
+ // As the name implies, waitForElementToBeRemoved should check `present` --> `removed`
1920
+ function initialCheck(elements) {
1921
+ if (isRemoved(elements)) {
1922
+ throw new Error('The element(s) given to waitForElementToBeRemoved are already removed. waitForElementToBeRemoved requires that the element(s) exist(s) before waiting for removal.');
1923
+ }
1924
+ }
1925
+ async function waitForElementToBeRemoved(callback, options) {
1926
+ // created here so we get a nice stacktrace
1927
+ const timeoutError = new Error('Timed out in waitForElementToBeRemoved.');
1928
+ if (typeof callback !== 'function') {
1929
+ initialCheck(callback);
1930
+ const elements = Array.isArray(callback) ? callback : [callback];
1931
+ const getRemainingElements = elements.map(element => {
1932
+ let parent = element.parentElement;
1933
+ if (parent === null) return () => null;
1934
+ while (parent.parentElement) parent = parent.parentElement;
1935
+ return () => parent.contains(element) ? element : null;
1936
+ });
1937
+ callback = () => getRemainingElements.map(c => c()).filter(Boolean);
1938
+ }
1939
+ initialCheck(callback());
1940
+ return waitForWrapper(() => {
1941
+ let result;
1942
+ try {
1943
+ result = callback();
1944
+ } catch (error) {
1945
+ if (error.name === 'TestingLibraryElementError') {
1946
+ return undefined;
1947
+ }
1948
+ throw error;
1949
+ }
1950
+ if (!isRemoved(result)) {
1951
+ throw timeoutError;
1952
+ }
1953
+ return undefined;
1954
+ }, options);
1955
+ }
1956
+
1957
+ /*
1958
+ eslint
1959
+ require-await: "off"
1960
+ */
1961
+
1962
+ const eventMap = {
1963
+ // Clipboard Events
1964
+ copy: {
1965
+ EventType: 'ClipboardEvent',
1966
+ defaultInit: {
1967
+ bubbles: true,
1968
+ cancelable: true,
1969
+ composed: true
1970
+ }
1971
+ },
1972
+ cut: {
1973
+ EventType: 'ClipboardEvent',
1974
+ defaultInit: {
1975
+ bubbles: true,
1976
+ cancelable: true,
1977
+ composed: true
1978
+ }
1979
+ },
1980
+ paste: {
1981
+ EventType: 'ClipboardEvent',
1982
+ defaultInit: {
1983
+ bubbles: true,
1984
+ cancelable: true,
1985
+ composed: true
1986
+ }
1987
+ },
1988
+ // Composition Events
1989
+ compositionEnd: {
1990
+ EventType: 'CompositionEvent',
1991
+ defaultInit: {
1992
+ bubbles: true,
1993
+ cancelable: true,
1994
+ composed: true
1995
+ }
1996
+ },
1997
+ compositionStart: {
1998
+ EventType: 'CompositionEvent',
1999
+ defaultInit: {
2000
+ bubbles: true,
2001
+ cancelable: true,
2002
+ composed: true
2003
+ }
2004
+ },
2005
+ compositionUpdate: {
2006
+ EventType: 'CompositionEvent',
2007
+ defaultInit: {
2008
+ bubbles: true,
2009
+ cancelable: true,
2010
+ composed: true
2011
+ }
2012
+ },
2013
+ // Keyboard Events
2014
+ keyDown: {
2015
+ EventType: 'KeyboardEvent',
2016
+ defaultInit: {
2017
+ bubbles: true,
2018
+ cancelable: true,
2019
+ charCode: 0,
2020
+ composed: true
2021
+ }
2022
+ },
2023
+ keyPress: {
2024
+ EventType: 'KeyboardEvent',
2025
+ defaultInit: {
2026
+ bubbles: true,
2027
+ cancelable: true,
2028
+ charCode: 0,
2029
+ composed: true
2030
+ }
2031
+ },
2032
+ keyUp: {
2033
+ EventType: 'KeyboardEvent',
2034
+ defaultInit: {
2035
+ bubbles: true,
2036
+ cancelable: true,
2037
+ charCode: 0,
2038
+ composed: true
2039
+ }
2040
+ },
2041
+ // Focus Events
2042
+ focus: {
2043
+ EventType: 'FocusEvent',
2044
+ defaultInit: {
2045
+ bubbles: false,
2046
+ cancelable: false,
2047
+ composed: true
2048
+ }
2049
+ },
2050
+ blur: {
2051
+ EventType: 'FocusEvent',
2052
+ defaultInit: {
2053
+ bubbles: false,
2054
+ cancelable: false,
2055
+ composed: true
2056
+ }
2057
+ },
2058
+ focusIn: {
2059
+ EventType: 'FocusEvent',
2060
+ defaultInit: {
2061
+ bubbles: true,
2062
+ cancelable: false,
2063
+ composed: true
2064
+ }
2065
+ },
2066
+ focusOut: {
2067
+ EventType: 'FocusEvent',
2068
+ defaultInit: {
2069
+ bubbles: true,
2070
+ cancelable: false,
2071
+ composed: true
2072
+ }
2073
+ },
2074
+ // Form Events
2075
+ change: {
2076
+ EventType: 'Event',
2077
+ defaultInit: {
2078
+ bubbles: true,
2079
+ cancelable: false
2080
+ }
2081
+ },
2082
+ input: {
2083
+ EventType: 'InputEvent',
2084
+ defaultInit: {
2085
+ bubbles: true,
2086
+ cancelable: false,
2087
+ composed: true
2088
+ }
2089
+ },
2090
+ invalid: {
2091
+ EventType: 'Event',
2092
+ defaultInit: {
2093
+ bubbles: false,
2094
+ cancelable: true
2095
+ }
2096
+ },
2097
+ submit: {
2098
+ EventType: 'Event',
2099
+ defaultInit: {
2100
+ bubbles: true,
2101
+ cancelable: true
2102
+ }
2103
+ },
2104
+ reset: {
2105
+ EventType: 'Event',
2106
+ defaultInit: {
2107
+ bubbles: true,
2108
+ cancelable: true
2109
+ }
2110
+ },
2111
+ // Mouse Events
2112
+ click: {
2113
+ EventType: 'MouseEvent',
2114
+ defaultInit: {
2115
+ bubbles: true,
2116
+ cancelable: true,
2117
+ button: 0,
2118
+ composed: true
2119
+ }
2120
+ },
2121
+ contextMenu: {
2122
+ EventType: 'MouseEvent',
2123
+ defaultInit: {
2124
+ bubbles: true,
2125
+ cancelable: true,
2126
+ composed: true
2127
+ }
2128
+ },
2129
+ dblClick: {
2130
+ EventType: 'MouseEvent',
2131
+ defaultInit: {
2132
+ bubbles: true,
2133
+ cancelable: true,
2134
+ composed: true
2135
+ }
2136
+ },
2137
+ drag: {
2138
+ EventType: 'DragEvent',
2139
+ defaultInit: {
2140
+ bubbles: true,
2141
+ cancelable: true,
2142
+ composed: true
2143
+ }
2144
+ },
2145
+ dragEnd: {
2146
+ EventType: 'DragEvent',
2147
+ defaultInit: {
2148
+ bubbles: true,
2149
+ cancelable: false,
2150
+ composed: true
2151
+ }
2152
+ },
2153
+ dragEnter: {
2154
+ EventType: 'DragEvent',
2155
+ defaultInit: {
2156
+ bubbles: true,
2157
+ cancelable: true,
2158
+ composed: true
2159
+ }
2160
+ },
2161
+ dragExit: {
2162
+ EventType: 'DragEvent',
2163
+ defaultInit: {
2164
+ bubbles: true,
2165
+ cancelable: false,
2166
+ composed: true
2167
+ }
2168
+ },
2169
+ dragLeave: {
2170
+ EventType: 'DragEvent',
2171
+ defaultInit: {
2172
+ bubbles: true,
2173
+ cancelable: false,
2174
+ composed: true
2175
+ }
2176
+ },
2177
+ dragOver: {
2178
+ EventType: 'DragEvent',
2179
+ defaultInit: {
2180
+ bubbles: true,
2181
+ cancelable: true,
2182
+ composed: true
2183
+ }
2184
+ },
2185
+ dragStart: {
2186
+ EventType: 'DragEvent',
2187
+ defaultInit: {
2188
+ bubbles: true,
2189
+ cancelable: true,
2190
+ composed: true
2191
+ }
2192
+ },
2193
+ drop: {
2194
+ EventType: 'DragEvent',
2195
+ defaultInit: {
2196
+ bubbles: true,
2197
+ cancelable: true,
2198
+ composed: true
2199
+ }
2200
+ },
2201
+ mouseDown: {
2202
+ EventType: 'MouseEvent',
2203
+ defaultInit: {
2204
+ bubbles: true,
2205
+ cancelable: true,
2206
+ composed: true
2207
+ }
2208
+ },
2209
+ mouseEnter: {
2210
+ EventType: 'MouseEvent',
2211
+ defaultInit: {
2212
+ bubbles: false,
2213
+ cancelable: false,
2214
+ composed: true
2215
+ }
2216
+ },
2217
+ mouseLeave: {
2218
+ EventType: 'MouseEvent',
2219
+ defaultInit: {
2220
+ bubbles: false,
2221
+ cancelable: false,
2222
+ composed: true
2223
+ }
2224
+ },
2225
+ mouseMove: {
2226
+ EventType: 'MouseEvent',
2227
+ defaultInit: {
2228
+ bubbles: true,
2229
+ cancelable: true,
2230
+ composed: true
2231
+ }
2232
+ },
2233
+ mouseOut: {
2234
+ EventType: 'MouseEvent',
2235
+ defaultInit: {
2236
+ bubbles: true,
2237
+ cancelable: true,
2238
+ composed: true
2239
+ }
2240
+ },
2241
+ mouseOver: {
2242
+ EventType: 'MouseEvent',
2243
+ defaultInit: {
2244
+ bubbles: true,
2245
+ cancelable: true,
2246
+ composed: true
2247
+ }
2248
+ },
2249
+ mouseUp: {
2250
+ EventType: 'MouseEvent',
2251
+ defaultInit: {
2252
+ bubbles: true,
2253
+ cancelable: true,
2254
+ composed: true
2255
+ }
2256
+ },
2257
+ // Selection Events
2258
+ select: {
2259
+ EventType: 'Event',
2260
+ defaultInit: {
2261
+ bubbles: true,
2262
+ cancelable: false
2263
+ }
2264
+ },
2265
+ // Touch Events
2266
+ touchCancel: {
2267
+ EventType: 'TouchEvent',
2268
+ defaultInit: {
2269
+ bubbles: true,
2270
+ cancelable: false,
2271
+ composed: true
2272
+ }
2273
+ },
2274
+ touchEnd: {
2275
+ EventType: 'TouchEvent',
2276
+ defaultInit: {
2277
+ bubbles: true,
2278
+ cancelable: true,
2279
+ composed: true
2280
+ }
2281
+ },
2282
+ touchMove: {
2283
+ EventType: 'TouchEvent',
2284
+ defaultInit: {
2285
+ bubbles: true,
2286
+ cancelable: true,
2287
+ composed: true
2288
+ }
2289
+ },
2290
+ touchStart: {
2291
+ EventType: 'TouchEvent',
2292
+ defaultInit: {
2293
+ bubbles: true,
2294
+ cancelable: true,
2295
+ composed: true
2296
+ }
2297
+ },
2298
+ // UI Events
2299
+ resize: {
2300
+ EventType: 'UIEvent',
2301
+ defaultInit: {
2302
+ bubbles: false,
2303
+ cancelable: false
2304
+ }
2305
+ },
2306
+ scroll: {
2307
+ EventType: 'UIEvent',
2308
+ defaultInit: {
2309
+ bubbles: false,
2310
+ cancelable: false
2311
+ }
2312
+ },
2313
+ // Wheel Events
2314
+ wheel: {
2315
+ EventType: 'WheelEvent',
2316
+ defaultInit: {
2317
+ bubbles: true,
2318
+ cancelable: true,
2319
+ composed: true
2320
+ }
2321
+ },
2322
+ // Media Events
2323
+ abort: {
2324
+ EventType: 'Event',
2325
+ defaultInit: {
2326
+ bubbles: false,
2327
+ cancelable: false
2328
+ }
2329
+ },
2330
+ canPlay: {
2331
+ EventType: 'Event',
2332
+ defaultInit: {
2333
+ bubbles: false,
2334
+ cancelable: false
2335
+ }
2336
+ },
2337
+ canPlayThrough: {
2338
+ EventType: 'Event',
2339
+ defaultInit: {
2340
+ bubbles: false,
2341
+ cancelable: false
2342
+ }
2343
+ },
2344
+ durationChange: {
2345
+ EventType: 'Event',
2346
+ defaultInit: {
2347
+ bubbles: false,
2348
+ cancelable: false
2349
+ }
2350
+ },
2351
+ emptied: {
2352
+ EventType: 'Event',
2353
+ defaultInit: {
2354
+ bubbles: false,
2355
+ cancelable: false
2356
+ }
2357
+ },
2358
+ encrypted: {
2359
+ EventType: 'Event',
2360
+ defaultInit: {
2361
+ bubbles: false,
2362
+ cancelable: false
2363
+ }
2364
+ },
2365
+ ended: {
2366
+ EventType: 'Event',
2367
+ defaultInit: {
2368
+ bubbles: false,
2369
+ cancelable: false
2370
+ }
2371
+ },
2372
+ loadedData: {
2373
+ EventType: 'Event',
2374
+ defaultInit: {
2375
+ bubbles: false,
2376
+ cancelable: false
2377
+ }
2378
+ },
2379
+ loadedMetadata: {
2380
+ EventType: 'Event',
2381
+ defaultInit: {
2382
+ bubbles: false,
2383
+ cancelable: false
2384
+ }
2385
+ },
2386
+ loadStart: {
2387
+ EventType: 'ProgressEvent',
2388
+ defaultInit: {
2389
+ bubbles: false,
2390
+ cancelable: false
2391
+ }
2392
+ },
2393
+ pause: {
2394
+ EventType: 'Event',
2395
+ defaultInit: {
2396
+ bubbles: false,
2397
+ cancelable: false
2398
+ }
2399
+ },
2400
+ play: {
2401
+ EventType: 'Event',
2402
+ defaultInit: {
2403
+ bubbles: false,
2404
+ cancelable: false
2405
+ }
2406
+ },
2407
+ playing: {
2408
+ EventType: 'Event',
2409
+ defaultInit: {
2410
+ bubbles: false,
2411
+ cancelable: false
2412
+ }
2413
+ },
2414
+ progress: {
2415
+ EventType: 'ProgressEvent',
2416
+ defaultInit: {
2417
+ bubbles: false,
2418
+ cancelable: false
2419
+ }
2420
+ },
2421
+ rateChange: {
2422
+ EventType: 'Event',
2423
+ defaultInit: {
2424
+ bubbles: false,
2425
+ cancelable: false
2426
+ }
2427
+ },
2428
+ seeked: {
2429
+ EventType: 'Event',
2430
+ defaultInit: {
2431
+ bubbles: false,
2432
+ cancelable: false
2433
+ }
2434
+ },
2435
+ seeking: {
2436
+ EventType: 'Event',
2437
+ defaultInit: {
2438
+ bubbles: false,
2439
+ cancelable: false
2440
+ }
2441
+ },
2442
+ stalled: {
2443
+ EventType: 'Event',
2444
+ defaultInit: {
2445
+ bubbles: false,
2446
+ cancelable: false
2447
+ }
2448
+ },
2449
+ suspend: {
2450
+ EventType: 'Event',
2451
+ defaultInit: {
2452
+ bubbles: false,
2453
+ cancelable: false
2454
+ }
2455
+ },
2456
+ timeUpdate: {
2457
+ EventType: 'Event',
2458
+ defaultInit: {
2459
+ bubbles: false,
2460
+ cancelable: false
2461
+ }
2462
+ },
2463
+ volumeChange: {
2464
+ EventType: 'Event',
2465
+ defaultInit: {
2466
+ bubbles: false,
2467
+ cancelable: false
2468
+ }
2469
+ },
2470
+ waiting: {
2471
+ EventType: 'Event',
2472
+ defaultInit: {
2473
+ bubbles: false,
2474
+ cancelable: false
2475
+ }
2476
+ },
2477
+ // Events
2478
+ load: {
2479
+ // TODO: load events can be UIEvent or Event depending on what generated them
2480
+ // This is where this abstraction breaks down.
2481
+ // But the common targets are <img />, <script /> and window.
2482
+ // Neither of these targets receive a UIEvent
2483
+ EventType: 'Event',
2484
+ defaultInit: {
2485
+ bubbles: false,
2486
+ cancelable: false
2487
+ }
2488
+ },
2489
+ error: {
2490
+ EventType: 'Event',
2491
+ defaultInit: {
2492
+ bubbles: false,
2493
+ cancelable: false
2494
+ }
2495
+ },
2496
+ // Animation Events
2497
+ animationStart: {
2498
+ EventType: 'AnimationEvent',
2499
+ defaultInit: {
2500
+ bubbles: true,
2501
+ cancelable: false
2502
+ }
2503
+ },
2504
+ animationEnd: {
2505
+ EventType: 'AnimationEvent',
2506
+ defaultInit: {
2507
+ bubbles: true,
2508
+ cancelable: false
2509
+ }
2510
+ },
2511
+ animationIteration: {
2512
+ EventType: 'AnimationEvent',
2513
+ defaultInit: {
2514
+ bubbles: true,
2515
+ cancelable: false
2516
+ }
2517
+ },
2518
+ // Transition Events
2519
+ transitionCancel: {
2520
+ EventType: 'TransitionEvent',
2521
+ defaultInit: {
2522
+ bubbles: true,
2523
+ cancelable: false
2524
+ }
2525
+ },
2526
+ transitionEnd: {
2527
+ EventType: 'TransitionEvent',
2528
+ defaultInit: {
2529
+ bubbles: true,
2530
+ cancelable: true
2531
+ }
2532
+ },
2533
+ transitionRun: {
2534
+ EventType: 'TransitionEvent',
2535
+ defaultInit: {
2536
+ bubbles: true,
2537
+ cancelable: false
2538
+ }
2539
+ },
2540
+ transitionStart: {
2541
+ EventType: 'TransitionEvent',
2542
+ defaultInit: {
2543
+ bubbles: true,
2544
+ cancelable: false
2545
+ }
2546
+ },
2547
+ // pointer events
2548
+ pointerOver: {
2549
+ EventType: 'PointerEvent',
2550
+ defaultInit: {
2551
+ bubbles: true,
2552
+ cancelable: true,
2553
+ composed: true
2554
+ }
2555
+ },
2556
+ pointerEnter: {
2557
+ EventType: 'PointerEvent',
2558
+ defaultInit: {
2559
+ bubbles: false,
2560
+ cancelable: false
2561
+ }
2562
+ },
2563
+ pointerDown: {
2564
+ EventType: 'PointerEvent',
2565
+ defaultInit: {
2566
+ bubbles: true,
2567
+ cancelable: true,
2568
+ composed: true
2569
+ }
2570
+ },
2571
+ pointerMove: {
2572
+ EventType: 'PointerEvent',
2573
+ defaultInit: {
2574
+ bubbles: true,
2575
+ cancelable: true,
2576
+ composed: true
2577
+ }
2578
+ },
2579
+ pointerUp: {
2580
+ EventType: 'PointerEvent',
2581
+ defaultInit: {
2582
+ bubbles: true,
2583
+ cancelable: true,
2584
+ composed: true
2585
+ }
2586
+ },
2587
+ pointerCancel: {
2588
+ EventType: 'PointerEvent',
2589
+ defaultInit: {
2590
+ bubbles: true,
2591
+ cancelable: false,
2592
+ composed: true
2593
+ }
2594
+ },
2595
+ pointerOut: {
2596
+ EventType: 'PointerEvent',
2597
+ defaultInit: {
2598
+ bubbles: true,
2599
+ cancelable: true,
2600
+ composed: true
2601
+ }
2602
+ },
2603
+ pointerLeave: {
2604
+ EventType: 'PointerEvent',
2605
+ defaultInit: {
2606
+ bubbles: false,
2607
+ cancelable: false
2608
+ }
2609
+ },
2610
+ gotPointerCapture: {
2611
+ EventType: 'PointerEvent',
2612
+ defaultInit: {
2613
+ bubbles: true,
2614
+ cancelable: false,
2615
+ composed: true
2616
+ }
2617
+ },
2618
+ lostPointerCapture: {
2619
+ EventType: 'PointerEvent',
2620
+ defaultInit: {
2621
+ bubbles: true,
2622
+ cancelable: false,
2623
+ composed: true
2624
+ }
2625
+ },
2626
+ // history events
2627
+ popState: {
2628
+ EventType: 'PopStateEvent',
2629
+ defaultInit: {
2630
+ bubbles: true,
2631
+ cancelable: false
2632
+ }
2633
+ },
2634
+ // window events
2635
+ offline: {
2636
+ EventType: 'Event',
2637
+ defaultInit: {
2638
+ bubbles: false,
2639
+ cancelable: false
2640
+ }
2641
+ },
2642
+ online: {
2643
+ EventType: 'Event',
2644
+ defaultInit: {
2645
+ bubbles: false,
2646
+ cancelable: false
2647
+ }
2648
+ },
2649
+ pageHide: {
2650
+ EventType: 'PageTransitionEvent',
2651
+ defaultInit: {
2652
+ bubbles: true,
2653
+ cancelable: true
2654
+ }
2655
+ },
2656
+ pageShow: {
2657
+ EventType: 'PageTransitionEvent',
2658
+ defaultInit: {
2659
+ bubbles: true,
2660
+ cancelable: true
2661
+ }
2662
+ }
2663
+ };
2664
+ const eventAliasMap = {
2665
+ doubleClick: 'dblClick'
2666
+ };
2667
+
2668
+ function fireEvent(element, event) {
2669
+ return getConfig().eventWrapper(() => {
2670
+ if (!event) {
2671
+ throw new Error("Unable to fire an event - please provide an event object.");
2672
+ }
2673
+ if (!element) {
2674
+ throw new Error("Unable to fire a \"" + event.type + "\" event - please provide a DOM element.");
2675
+ }
2676
+ return element.dispatchEvent(event);
2677
+ });
2678
+ }
2679
+ function createEvent(eventName, node, init, _temp) {
2680
+ let {
2681
+ EventType = 'Event',
2682
+ defaultInit = {}
2683
+ } = _temp === void 0 ? {} : _temp;
2684
+ if (!node) {
2685
+ throw new Error("Unable to fire a \"" + eventName + "\" event - please provide a DOM element.");
2686
+ }
2687
+ const eventInit = {
2688
+ ...defaultInit,
2689
+ ...init
2690
+ };
2691
+ const {
2692
+ target: {
2693
+ value,
2694
+ files,
2695
+ ...targetProperties
2696
+ } = {}
2697
+ } = eventInit;
2698
+ if (value !== undefined) {
2699
+ setNativeValue(node, value);
2700
+ }
2701
+ if (files !== undefined) {
2702
+ // input.files is a read-only property so this is not allowed:
2703
+ // input.files = [file]
2704
+ // so we have to use this workaround to set the property
2705
+ Object.defineProperty(node, 'files', {
2706
+ configurable: true,
2707
+ enumerable: true,
2708
+ writable: true,
2709
+ value: files
2710
+ });
2711
+ }
2712
+ Object.assign(node, targetProperties);
2713
+ const window = getWindowFromNode(node);
2714
+ const EventConstructor = window[EventType] || window.Event;
2715
+ let event;
2716
+ /* istanbul ignore else */
2717
+ if (typeof EventConstructor === 'function') {
2718
+ event = new EventConstructor(eventName, eventInit);
2719
+ } else {
2720
+ // IE11 polyfill from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
2721
+ event = window.document.createEvent(EventType);
2722
+ const {
2723
+ bubbles,
2724
+ cancelable,
2725
+ detail,
2726
+ ...otherInit
2727
+ } = eventInit;
2728
+ event.initEvent(eventName, bubbles, cancelable, detail);
2729
+ Object.keys(otherInit).forEach(eventKey => {
2730
+ event[eventKey] = otherInit[eventKey];
2731
+ });
2732
+ }
2733
+
2734
+ // DataTransfer is not supported in jsdom: https://github.com/jsdom/jsdom/issues/1568
2735
+ const dataTransferProperties = ['dataTransfer', 'clipboardData'];
2736
+ dataTransferProperties.forEach(dataTransferKey => {
2737
+ const dataTransferValue = eventInit[dataTransferKey];
2738
+ if (typeof dataTransferValue === 'object') {
2739
+ /* istanbul ignore if */
2740
+ if (typeof window.DataTransfer === 'function') {
2741
+ Object.defineProperty(event, dataTransferKey, {
2742
+ value: Object.getOwnPropertyNames(dataTransferValue).reduce((acc, propName) => {
2743
+ Object.defineProperty(acc, propName, {
2744
+ value: dataTransferValue[propName]
2745
+ });
2746
+ return acc;
2747
+ }, new window.DataTransfer())
2748
+ });
2749
+ } else {
2750
+ Object.defineProperty(event, dataTransferKey, {
2751
+ value: dataTransferValue
2752
+ });
2753
+ }
2754
+ }
2755
+ });
2756
+ return event;
2757
+ }
2758
+ Object.keys(eventMap).forEach(key => {
2759
+ const {
2760
+ EventType,
2761
+ defaultInit
2762
+ } = eventMap[key];
2763
+ const eventName = key.toLowerCase();
2764
+ createEvent[key] = (node, init) => createEvent(eventName, node, init, {
2765
+ EventType,
2766
+ defaultInit
2767
+ });
2768
+ fireEvent[key] = (node, init) => fireEvent(node, createEvent[key](node, init));
2769
+ });
2770
+
2771
+ // function written after some investigation here:
2772
+ // https://github.com/facebook/react/issues/10135#issuecomment-401496776
2773
+ function setNativeValue(element, value) {
2774
+ const {
2775
+ set: valueSetter
2776
+ } = Object.getOwnPropertyDescriptor(element, 'value') || {};
2777
+ const prototype = Object.getPrototypeOf(element);
2778
+ const {
2779
+ set: prototypeValueSetter
2780
+ } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
2781
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
2782
+ prototypeValueSetter.call(element, value);
2783
+ } else {
2784
+ /* istanbul ignore if */
2785
+ // eslint-disable-next-line no-lonely-if -- Can't be ignored by istanbul otherwise
2786
+ if (valueSetter) {
2787
+ valueSetter.call(element, value);
2788
+ } else {
2789
+ throw new Error('The given element does not have a value setter');
2790
+ }
2791
+ }
2792
+ }
2793
+ Object.keys(eventAliasMap).forEach(aliasKey => {
2794
+ const key = eventAliasMap[aliasKey];
2795
+ fireEvent[aliasKey] = function () {
2796
+ return fireEvent[key](...arguments);
2797
+ };
2798
+ });
2799
+
2800
+ /* eslint complexity:["error", 9] */
2801
+
2802
+ // WARNING: `lz-string` only has a default export but statically we assume named exports are allowed
2803
+ function unindent(string) {
2804
+ // remove white spaces first, to save a few bytes.
2805
+ // testing-playground will reformat on load any ways.
2806
+ return string.replace(/[ \t]*[\n][ \t]*/g, '\n');
2807
+ }
2808
+ function encode(value) {
2809
+ return lzString.compressToEncodedURIComponent(unindent(value));
2810
+ }
2811
+ function getPlaygroundUrl(markup) {
2812
+ return "https://testing-playground.com/#markup=" + encode(markup);
2813
+ }
2814
+ const debug = (element, maxLength, options) => Array.isArray(element) ? element.forEach(el => logDOM(el, maxLength, options)) : logDOM(element, maxLength, options);
2815
+ const logTestingPlaygroundURL = function (element) {
2816
+ if (element === void 0) {
2817
+ element = getDocument().body;
2818
+ }
2819
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2820
+ if (!element || !('innerHTML' in element)) {
2821
+ console.log("The element you're providing isn't a valid DOM element.");
2822
+ return;
2823
+ }
2824
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2825
+ if (!element.innerHTML) {
2826
+ console.log("The provided element doesn't have any children.");
2827
+ return;
2828
+ }
2829
+ const playgroundUrl = getPlaygroundUrl(element.innerHTML);
2830
+ console.log("Open this URL in your browser\n\n" + playgroundUrl);
2831
+ return playgroundUrl;
2832
+ };
2833
+ const initialValue = {
2834
+ debug,
2835
+ logTestingPlaygroundURL
2836
+ };
2837
+ const screen = typeof document !== 'undefined' && document.body // eslint-disable-line @typescript-eslint/no-unnecessary-condition
2838
+ ? getQueriesForElement(document.body, queries, initialValue) : Object.keys(queries).reduce((helpers, key) => {
2839
+ // `key` is for all intents and purposes the type of keyof `helpers`, which itself is the type of `initialValue` plus incoming properties from `queries`
2840
+ // if `Object.keys(something)` returned Array<keyof typeof something> this explicit type assertion would not be necessary
2841
+ // see https://stackoverflow.com/questions/55012174/why-doesnt-object-keys-return-a-keyof-type-in-typescript
2842
+ helpers[key] = () => {
2843
+ throw new TypeError('For queries bound to document.body a global document has to be available... Learn more: https://testing-library.com/s/screen-global-error');
2844
+ };
2845
+ return helpers;
2846
+ }, initialValue);
2847
+
2848
+ export { buildQueries, configure, createEvent, findAllByAltText, findAllByDisplayValue, findAllByLabelText, findAllByPlaceholderText, findAllByRole, findAllByTestId, findAllByText, findAllByTitle, findByAltText, findByDisplayValue, findByLabelText, findByPlaceholderText, findByRole, findByTestId, findByText, findByTitle, fireEvent, getAllByAltText, getAllByDisplayValue, getAllByLabelTextWithSuggestions as getAllByLabelText, getAllByPlaceholderText, getAllByRole, getAllByTestId, getAllByText, getAllByTitle, getByAltText, getByDisplayValue, getByLabelTextWithSuggestions as getByLabelText, getByPlaceholderText, getByRole, getByTestId, getByText, getByTitle, getConfig, getDefaultNormalizer, getElementError, getMultipleElementsFoundError, getNodeText, getQueriesForElement, getRoles, getSuggestedQuery, isInaccessible, logDOM, logRoles, makeFindQuery, makeGetAllQuery, makeSingleQuery, prettyDOM, queries, queryAllByAltTextWithSuggestions as queryAllByAltText, queryAllByAttribute, queryAllByDisplayValueWithSuggestions as queryAllByDisplayValue, queryAllByLabelTextWithSuggestions as queryAllByLabelText, queryAllByPlaceholderTextWithSuggestions as queryAllByPlaceholderText, queryAllByRoleWithSuggestions as queryAllByRole, queryAllByTestIdWithSuggestions as queryAllByTestId, queryAllByTextWithSuggestions as queryAllByText, queryAllByTitleWithSuggestions as queryAllByTitle, queryByAltText, queryByAttribute, queryByDisplayValue, queryByLabelText, queryByPlaceholderText, queryByRole, queryByTestId, queryByText, queryByTitle, queryHelpers, screen, waitForWrapper as waitFor, waitForElementToBeRemoved, getQueriesForElement as within, wrapAllByQueryWithSuggestion, wrapSingleQueryWithSuggestion };
node_modules/@testing-library/dom/dist/@testing-library/dom.umd.js ADDED
The diff for this file is too large to render. See raw diff
 
node_modules/@testing-library/dom/dist/@testing-library/dom.umd.js.map ADDED
The diff for this file is too large to render. See raw diff
 
node_modules/@testing-library/dom/dist/@testing-library/dom.umd.min.js ADDED
The diff for this file is too large to render. See raw diff
 
node_modules/@testing-library/dom/dist/@testing-library/dom.umd.min.js.map ADDED
The diff for this file is too large to render. See raw diff
 
node_modules/@testing-library/dom/dist/DOMElementFilter.js ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = createDOMElementFilter;
7
+ exports.test = void 0;
8
+ /**
9
+ * Source: https://github.com/facebook/jest/blob/e7bb6a1e26ffab90611b2593912df15b69315611/packages/pretty-format/src/plugins/DOMElement.ts
10
+ */
11
+ /* eslint-disable -- trying to stay as close to the original as possible */
12
+ /* istanbul ignore file */
13
+
14
+ function escapeHTML(str) {
15
+ return str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
16
+ }
17
+ // Return empty string if keys is empty.
18
+ const printProps = (keys, props, config, indentation, depth, refs, printer) => {
19
+ const indentationNext = indentation + config.indent;
20
+ const colors = config.colors;
21
+ return keys.map(key => {
22
+ const value = props[key];
23
+ let printed = printer(value, config, indentationNext, depth, refs);
24
+ if (typeof value !== 'string') {
25
+ if (printed.indexOf('\n') !== -1) {
26
+ printed = config.spacingOuter + indentationNext + printed + config.spacingOuter + indentation;
27
+ }
28
+ printed = '{' + printed + '}';
29
+ }
30
+ return config.spacingInner + indentation + colors.prop.open + key + colors.prop.close + '=' + colors.value.open + printed + colors.value.close;
31
+ }).join('');
32
+ };
33
+
34
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#node_type_constants
35
+ const NodeTypeTextNode = 3;
36
+
37
+ // Return empty string if children is empty.
38
+ const printChildren = (children, config, indentation, depth, refs, printer) => children.map(child => {
39
+ const printedChild = typeof child === 'string' ? printText(child, config) : printer(child, config, indentation, depth, refs);
40
+ if (printedChild === '' && typeof child === 'object' && child !== null && child.nodeType !== NodeTypeTextNode) {
41
+ // A plugin serialized this Node to '' meaning we should ignore it.
42
+ return '';
43
+ }
44
+ return config.spacingOuter + indentation + printedChild;
45
+ }).join('');
46
+ const printText = (text, config) => {
47
+ const contentColor = config.colors.content;
48
+ return contentColor.open + escapeHTML(text) + contentColor.close;
49
+ };
50
+ const printComment = (comment, config) => {
51
+ const commentColor = config.colors.comment;
52
+ return commentColor.open + '<!--' + escapeHTML(comment) + '-->' + commentColor.close;
53
+ };
54
+
55
+ // Separate the functions to format props, children, and element,
56
+ // so a plugin could override a particular function, if needed.
57
+ // Too bad, so sad: the traditional (but unnecessary) space
58
+ // in a self-closing tagColor requires a second test of printedProps.
59
+ const printElement = (type, printedProps, printedChildren, config, indentation) => {
60
+ const tagColor = config.colors.tag;
61
+ return tagColor.open + '<' + type + (printedProps && tagColor.close + printedProps + config.spacingOuter + indentation + tagColor.open) + (printedChildren ? '>' + tagColor.close + printedChildren + config.spacingOuter + indentation + tagColor.open + '</' + type : (printedProps && !config.min ? '' : ' ') + '/') + '>' + tagColor.close;
62
+ };
63
+ const printElementAsLeaf = (type, config) => {
64
+ const tagColor = config.colors.tag;
65
+ return tagColor.open + '<' + type + tagColor.close + ' …' + tagColor.open + ' />' + tagColor.close;
66
+ };
67
+ const ELEMENT_NODE = 1;
68
+ const TEXT_NODE = 3;
69
+ const COMMENT_NODE = 8;
70
+ const FRAGMENT_NODE = 11;
71
+ const ELEMENT_REGEXP = /^((HTML|SVG)\w*)?Element$/;
72
+ const isCustomElement = val => {
73
+ const {
74
+ tagName
75
+ } = val;
76
+ return Boolean(typeof tagName === 'string' && tagName.includes('-') || typeof val.hasAttribute === 'function' && val.hasAttribute('is'));
77
+ };
78
+ const testNode = val => {
79
+ const constructorName = val.constructor.name;
80
+ const {
81
+ nodeType
82
+ } = val;
83
+ return nodeType === ELEMENT_NODE && (ELEMENT_REGEXP.test(constructorName) || isCustomElement(val)) || nodeType === TEXT_NODE && constructorName === 'Text' || nodeType === COMMENT_NODE && constructorName === 'Comment' || nodeType === FRAGMENT_NODE && constructorName === 'DocumentFragment';
84
+ };
85
+ const test = val => (val?.constructor?.name || isCustomElement(val)) && testNode(val);
86
+ exports.test = test;
87
+ function nodeIsText(node) {
88
+ return node.nodeType === TEXT_NODE;
89
+ }
90
+ function nodeIsComment(node) {
91
+ return node.nodeType === COMMENT_NODE;
92
+ }
93
+ function nodeIsFragment(node) {
94
+ return node.nodeType === FRAGMENT_NODE;
95
+ }
96
+ function createDOMElementFilter(filterNode) {
97
+ return {
98
+ test: val => (val?.constructor?.name || isCustomElement(val)) && testNode(val),
99
+ serialize: (node, config, indentation, depth, refs, printer) => {
100
+ if (nodeIsText(node)) {
101
+ return printText(node.data, config);
102
+ }
103
+ if (nodeIsComment(node)) {
104
+ return printComment(node.data, config);
105
+ }
106
+ const type = nodeIsFragment(node) ? `DocumentFragment` : node.tagName.toLowerCase();
107
+ if (++depth > config.maxDepth) {
108
+ return printElementAsLeaf(type, config);
109
+ }
110
+ return printElement(type, printProps(nodeIsFragment(node) ? [] : Array.from(node.attributes).map(attr => attr.name).sort(), nodeIsFragment(node) ? {} : Array.from(node.attributes).reduce((props, attribute) => {
111
+ props[attribute.name] = attribute.value;
112
+ return props;
113
+ }, {}), config, indentation + config.indent, depth, refs, printer), printChildren(Array.prototype.slice.call(node.childNodes || node.children).filter(filterNode), config, indentation + config.indent, depth, refs, printer), config, indentation);
114
+ }
115
+ };
116
+ }
node_modules/@testing-library/dom/dist/config.js ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.configure = configure;
7
+ exports.getConfig = getConfig;
8
+ exports.runWithExpensiveErrorDiagnosticsDisabled = runWithExpensiveErrorDiagnosticsDisabled;
9
+ var _prettyDom = require("./pretty-dom");
10
+ // It would be cleaner for this to live inside './queries', but
11
+ // other parts of the code assume that all exports from
12
+ // './queries' are query functions.
13
+ let config = {
14
+ testIdAttribute: 'data-testid',
15
+ asyncUtilTimeout: 1000,
16
+ // asyncWrapper and advanceTimersWrapper is to support React's async `act` function.
17
+ // forcing react-testing-library to wrap all async functions would've been
18
+ // a total nightmare (consider wrapping every findBy* query and then also
19
+ // updating `within` so those would be wrapped too. Total nightmare).
20
+ // so we have this config option that's really only intended for
21
+ // react-testing-library to use. For that reason, this feature will remain
22
+ // undocumented.
23
+ asyncWrapper: cb => cb(),
24
+ unstable_advanceTimersWrapper: cb => cb(),
25
+ eventWrapper: cb => cb(),
26
+ // default value for the `hidden` option in `ByRole` queries
27
+ defaultHidden: false,
28
+ // default value for the `ignore` option in `ByText` queries
29
+ defaultIgnore: 'script, style',
30
+ // showOriginalStackTrace flag to show the full error stack traces for async errors
31
+ showOriginalStackTrace: false,
32
+ // throw errors w/ suggestions for better queries. Opt in so off by default.
33
+ throwSuggestions: false,
34
+ // called when getBy* queries fail. (message, container) => Error
35
+ getElementError(message, container) {
36
+ const prettifiedDOM = (0, _prettyDom.prettyDOM)(container);
37
+ const error = new Error([message, `Ignored nodes: comments, ${config.defaultIgnore}\n${prettifiedDOM}`].filter(Boolean).join('\n\n'));
38
+ error.name = 'TestingLibraryElementError';
39
+ return error;
40
+ },
41
+ _disableExpensiveErrorDiagnostics: false,
42
+ computedStyleSupportsPseudoElements: false
43
+ };
44
+ function runWithExpensiveErrorDiagnosticsDisabled(callback) {
45
+ try {
46
+ config._disableExpensiveErrorDiagnostics = true;
47
+ return callback();
48
+ } finally {
49
+ config._disableExpensiveErrorDiagnostics = false;
50
+ }
51
+ }
52
+ function configure(newConfig) {
53
+ if (typeof newConfig === 'function') {
54
+ // Pass the existing config out to the provided function
55
+ // and accept a delta in return
56
+ newConfig = newConfig(config);
57
+ }
58
+
59
+ // Merge the incoming config delta
60
+ config = {
61
+ ...config,
62
+ ...newConfig
63
+ };
64
+ }
65
+ function getConfig() {
66
+ return config;
67
+ }
node_modules/@testing-library/dom/dist/event-map.js ADDED
@@ -0,0 +1,711 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.eventMap = exports.eventAliasMap = void 0;
7
+ const eventMap = exports.eventMap = {
8
+ // Clipboard Events
9
+ copy: {
10
+ EventType: 'ClipboardEvent',
11
+ defaultInit: {
12
+ bubbles: true,
13
+ cancelable: true,
14
+ composed: true
15
+ }
16
+ },
17
+ cut: {
18
+ EventType: 'ClipboardEvent',
19
+ defaultInit: {
20
+ bubbles: true,
21
+ cancelable: true,
22
+ composed: true
23
+ }
24
+ },
25
+ paste: {
26
+ EventType: 'ClipboardEvent',
27
+ defaultInit: {
28
+ bubbles: true,
29
+ cancelable: true,
30
+ composed: true
31
+ }
32
+ },
33
+ // Composition Events
34
+ compositionEnd: {
35
+ EventType: 'CompositionEvent',
36
+ defaultInit: {
37
+ bubbles: true,
38
+ cancelable: true,
39
+ composed: true
40
+ }
41
+ },
42
+ compositionStart: {
43
+ EventType: 'CompositionEvent',
44
+ defaultInit: {
45
+ bubbles: true,
46
+ cancelable: true,
47
+ composed: true
48
+ }
49
+ },
50
+ compositionUpdate: {
51
+ EventType: 'CompositionEvent',
52
+ defaultInit: {
53
+ bubbles: true,
54
+ cancelable: true,
55
+ composed: true
56
+ }
57
+ },
58
+ // Keyboard Events
59
+ keyDown: {
60
+ EventType: 'KeyboardEvent',
61
+ defaultInit: {
62
+ bubbles: true,
63
+ cancelable: true,
64
+ charCode: 0,
65
+ composed: true
66
+ }
67
+ },
68
+ keyPress: {
69
+ EventType: 'KeyboardEvent',
70
+ defaultInit: {
71
+ bubbles: true,
72
+ cancelable: true,
73
+ charCode: 0,
74
+ composed: true
75
+ }
76
+ },
77
+ keyUp: {
78
+ EventType: 'KeyboardEvent',
79
+ defaultInit: {
80
+ bubbles: true,
81
+ cancelable: true,
82
+ charCode: 0,
83
+ composed: true
84
+ }
85
+ },
86
+ // Focus Events
87
+ focus: {
88
+ EventType: 'FocusEvent',
89
+ defaultInit: {
90
+ bubbles: false,
91
+ cancelable: false,
92
+ composed: true
93
+ }
94
+ },
95
+ blur: {
96
+ EventType: 'FocusEvent',
97
+ defaultInit: {
98
+ bubbles: false,
99
+ cancelable: false,
100
+ composed: true
101
+ }
102
+ },
103
+ focusIn: {
104
+ EventType: 'FocusEvent',
105
+ defaultInit: {
106
+ bubbles: true,
107
+ cancelable: false,
108
+ composed: true
109
+ }
110
+ },
111
+ focusOut: {
112
+ EventType: 'FocusEvent',
113
+ defaultInit: {
114
+ bubbles: true,
115
+ cancelable: false,
116
+ composed: true
117
+ }
118
+ },
119
+ // Form Events
120
+ change: {
121
+ EventType: 'Event',
122
+ defaultInit: {
123
+ bubbles: true,
124
+ cancelable: false
125
+ }
126
+ },
127
+ input: {
128
+ EventType: 'InputEvent',
129
+ defaultInit: {
130
+ bubbles: true,
131
+ cancelable: false,
132
+ composed: true
133
+ }
134
+ },
135
+ invalid: {
136
+ EventType: 'Event',
137
+ defaultInit: {
138
+ bubbles: false,
139
+ cancelable: true
140
+ }
141
+ },
142
+ submit: {
143
+ EventType: 'Event',
144
+ defaultInit: {
145
+ bubbles: true,
146
+ cancelable: true
147
+ }
148
+ },
149
+ reset: {
150
+ EventType: 'Event',
151
+ defaultInit: {
152
+ bubbles: true,
153
+ cancelable: true
154
+ }
155
+ },
156
+ // Mouse Events
157
+ click: {
158
+ EventType: 'MouseEvent',
159
+ defaultInit: {
160
+ bubbles: true,
161
+ cancelable: true,
162
+ button: 0,
163
+ composed: true
164
+ }
165
+ },
166
+ contextMenu: {
167
+ EventType: 'MouseEvent',
168
+ defaultInit: {
169
+ bubbles: true,
170
+ cancelable: true,
171
+ composed: true
172
+ }
173
+ },
174
+ dblClick: {
175
+ EventType: 'MouseEvent',
176
+ defaultInit: {
177
+ bubbles: true,
178
+ cancelable: true,
179
+ composed: true
180
+ }
181
+ },
182
+ drag: {
183
+ EventType: 'DragEvent',
184
+ defaultInit: {
185
+ bubbles: true,
186
+ cancelable: true,
187
+ composed: true
188
+ }
189
+ },
190
+ dragEnd: {
191
+ EventType: 'DragEvent',
192
+ defaultInit: {
193
+ bubbles: true,
194
+ cancelable: false,
195
+ composed: true
196
+ }
197
+ },
198
+ dragEnter: {
199
+ EventType: 'DragEvent',
200
+ defaultInit: {
201
+ bubbles: true,
202
+ cancelable: true,
203
+ composed: true
204
+ }
205
+ },
206
+ dragExit: {
207
+ EventType: 'DragEvent',
208
+ defaultInit: {
209
+ bubbles: true,
210
+ cancelable: false,
211
+ composed: true
212
+ }
213
+ },
214
+ dragLeave: {
215
+ EventType: 'DragEvent',
216
+ defaultInit: {
217
+ bubbles: true,
218
+ cancelable: false,
219
+ composed: true
220
+ }
221
+ },
222
+ dragOver: {
223
+ EventType: 'DragEvent',
224
+ defaultInit: {
225
+ bubbles: true,
226
+ cancelable: true,
227
+ composed: true
228
+ }
229
+ },
230
+ dragStart: {
231
+ EventType: 'DragEvent',
232
+ defaultInit: {
233
+ bubbles: true,
234
+ cancelable: true,
235
+ composed: true
236
+ }
237
+ },
238
+ drop: {
239
+ EventType: 'DragEvent',
240
+ defaultInit: {
241
+ bubbles: true,
242
+ cancelable: true,
243
+ composed: true
244
+ }
245
+ },
246
+ mouseDown: {
247
+ EventType: 'MouseEvent',
248
+ defaultInit: {
249
+ bubbles: true,
250
+ cancelable: true,
251
+ composed: true
252
+ }
253
+ },
254
+ mouseEnter: {
255
+ EventType: 'MouseEvent',
256
+ defaultInit: {
257
+ bubbles: false,
258
+ cancelable: false,
259
+ composed: true
260
+ }
261
+ },
262
+ mouseLeave: {
263
+ EventType: 'MouseEvent',
264
+ defaultInit: {
265
+ bubbles: false,
266
+ cancelable: false,
267
+ composed: true
268
+ }
269
+ },
270
+ mouseMove: {
271
+ EventType: 'MouseEvent',
272
+ defaultInit: {
273
+ bubbles: true,
274
+ cancelable: true,
275
+ composed: true
276
+ }
277
+ },
278
+ mouseOut: {
279
+ EventType: 'MouseEvent',
280
+ defaultInit: {
281
+ bubbles: true,
282
+ cancelable: true,
283
+ composed: true
284
+ }
285
+ },
286
+ mouseOver: {
287
+ EventType: 'MouseEvent',
288
+ defaultInit: {
289
+ bubbles: true,
290
+ cancelable: true,
291
+ composed: true
292
+ }
293
+ },
294
+ mouseUp: {
295
+ EventType: 'MouseEvent',
296
+ defaultInit: {
297
+ bubbles: true,
298
+ cancelable: true,
299
+ composed: true
300
+ }
301
+ },
302
+ // Selection Events
303
+ select: {
304
+ EventType: 'Event',
305
+ defaultInit: {
306
+ bubbles: true,
307
+ cancelable: false
308
+ }
309
+ },
310
+ // Touch Events
311
+ touchCancel: {
312
+ EventType: 'TouchEvent',
313
+ defaultInit: {
314
+ bubbles: true,
315
+ cancelable: false,
316
+ composed: true
317
+ }
318
+ },
319
+ touchEnd: {
320
+ EventType: 'TouchEvent',
321
+ defaultInit: {
322
+ bubbles: true,
323
+ cancelable: true,
324
+ composed: true
325
+ }
326
+ },
327
+ touchMove: {
328
+ EventType: 'TouchEvent',
329
+ defaultInit: {
330
+ bubbles: true,
331
+ cancelable: true,
332
+ composed: true
333
+ }
334
+ },
335
+ touchStart: {
336
+ EventType: 'TouchEvent',
337
+ defaultInit: {
338
+ bubbles: true,
339
+ cancelable: true,
340
+ composed: true
341
+ }
342
+ },
343
+ // UI Events
344
+ resize: {
345
+ EventType: 'UIEvent',
346
+ defaultInit: {
347
+ bubbles: false,
348
+ cancelable: false
349
+ }
350
+ },
351
+ scroll: {
352
+ EventType: 'UIEvent',
353
+ defaultInit: {
354
+ bubbles: false,
355
+ cancelable: false
356
+ }
357
+ },
358
+ // Wheel Events
359
+ wheel: {
360
+ EventType: 'WheelEvent',
361
+ defaultInit: {
362
+ bubbles: true,
363
+ cancelable: true,
364
+ composed: true
365
+ }
366
+ },
367
+ // Media Events
368
+ abort: {
369
+ EventType: 'Event',
370
+ defaultInit: {
371
+ bubbles: false,
372
+ cancelable: false
373
+ }
374
+ },
375
+ canPlay: {
376
+ EventType: 'Event',
377
+ defaultInit: {
378
+ bubbles: false,
379
+ cancelable: false
380
+ }
381
+ },
382
+ canPlayThrough: {
383
+ EventType: 'Event',
384
+ defaultInit: {
385
+ bubbles: false,
386
+ cancelable: false
387
+ }
388
+ },
389
+ durationChange: {
390
+ EventType: 'Event',
391
+ defaultInit: {
392
+ bubbles: false,
393
+ cancelable: false
394
+ }
395
+ },
396
+ emptied: {
397
+ EventType: 'Event',
398
+ defaultInit: {
399
+ bubbles: false,
400
+ cancelable: false
401
+ }
402
+ },
403
+ encrypted: {
404
+ EventType: 'Event',
405
+ defaultInit: {
406
+ bubbles: false,
407
+ cancelable: false
408
+ }
409
+ },
410
+ ended: {
411
+ EventType: 'Event',
412
+ defaultInit: {
413
+ bubbles: false,
414
+ cancelable: false
415
+ }
416
+ },
417
+ loadedData: {
418
+ EventType: 'Event',
419
+ defaultInit: {
420
+ bubbles: false,
421
+ cancelable: false
422
+ }
423
+ },
424
+ loadedMetadata: {
425
+ EventType: 'Event',
426
+ defaultInit: {
427
+ bubbles: false,
428
+ cancelable: false
429
+ }
430
+ },
431
+ loadStart: {
432
+ EventType: 'ProgressEvent',
433
+ defaultInit: {
434
+ bubbles: false,
435
+ cancelable: false
436
+ }
437
+ },
438
+ pause: {
439
+ EventType: 'Event',
440
+ defaultInit: {
441
+ bubbles: false,
442
+ cancelable: false
443
+ }
444
+ },
445
+ play: {
446
+ EventType: 'Event',
447
+ defaultInit: {
448
+ bubbles: false,
449
+ cancelable: false
450
+ }
451
+ },
452
+ playing: {
453
+ EventType: 'Event',
454
+ defaultInit: {
455
+ bubbles: false,
456
+ cancelable: false
457
+ }
458
+ },
459
+ progress: {
460
+ EventType: 'ProgressEvent',
461
+ defaultInit: {
462
+ bubbles: false,
463
+ cancelable: false
464
+ }
465
+ },
466
+ rateChange: {
467
+ EventType: 'Event',
468
+ defaultInit: {
469
+ bubbles: false,
470
+ cancelable: false
471
+ }
472
+ },
473
+ seeked: {
474
+ EventType: 'Event',
475
+ defaultInit: {
476
+ bubbles: false,
477
+ cancelable: false
478
+ }
479
+ },
480
+ seeking: {
481
+ EventType: 'Event',
482
+ defaultInit: {
483
+ bubbles: false,
484
+ cancelable: false
485
+ }
486
+ },
487
+ stalled: {
488
+ EventType: 'Event',
489
+ defaultInit: {
490
+ bubbles: false,
491
+ cancelable: false
492
+ }
493
+ },
494
+ suspend: {
495
+ EventType: 'Event',
496
+ defaultInit: {
497
+ bubbles: false,
498
+ cancelable: false
499
+ }
500
+ },
501
+ timeUpdate: {
502
+ EventType: 'Event',
503
+ defaultInit: {
504
+ bubbles: false,
505
+ cancelable: false
506
+ }
507
+ },
508
+ volumeChange: {
509
+ EventType: 'Event',
510
+ defaultInit: {
511
+ bubbles: false,
512
+ cancelable: false
513
+ }
514
+ },
515
+ waiting: {
516
+ EventType: 'Event',
517
+ defaultInit: {
518
+ bubbles: false,
519
+ cancelable: false
520
+ }
521
+ },
522
+ // Events
523
+ load: {
524
+ // TODO: load events can be UIEvent or Event depending on what generated them
525
+ // This is where this abstraction breaks down.
526
+ // But the common targets are <img />, <script /> and window.
527
+ // Neither of these targets receive a UIEvent
528
+ EventType: 'Event',
529
+ defaultInit: {
530
+ bubbles: false,
531
+ cancelable: false
532
+ }
533
+ },
534
+ error: {
535
+ EventType: 'Event',
536
+ defaultInit: {
537
+ bubbles: false,
538
+ cancelable: false
539
+ }
540
+ },
541
+ // Animation Events
542
+ animationStart: {
543
+ EventType: 'AnimationEvent',
544
+ defaultInit: {
545
+ bubbles: true,
546
+ cancelable: false
547
+ }
548
+ },
549
+ animationEnd: {
550
+ EventType: 'AnimationEvent',
551
+ defaultInit: {
552
+ bubbles: true,
553
+ cancelable: false
554
+ }
555
+ },
556
+ animationIteration: {
557
+ EventType: 'AnimationEvent',
558
+ defaultInit: {
559
+ bubbles: true,
560
+ cancelable: false
561
+ }
562
+ },
563
+ // Transition Events
564
+ transitionCancel: {
565
+ EventType: 'TransitionEvent',
566
+ defaultInit: {
567
+ bubbles: true,
568
+ cancelable: false
569
+ }
570
+ },
571
+ transitionEnd: {
572
+ EventType: 'TransitionEvent',
573
+ defaultInit: {
574
+ bubbles: true,
575
+ cancelable: true
576
+ }
577
+ },
578
+ transitionRun: {
579
+ EventType: 'TransitionEvent',
580
+ defaultInit: {
581
+ bubbles: true,
582
+ cancelable: false
583
+ }
584
+ },
585
+ transitionStart: {
586
+ EventType: 'TransitionEvent',
587
+ defaultInit: {
588
+ bubbles: true,
589
+ cancelable: false
590
+ }
591
+ },
592
+ // pointer events
593
+ pointerOver: {
594
+ EventType: 'PointerEvent',
595
+ defaultInit: {
596
+ bubbles: true,
597
+ cancelable: true,
598
+ composed: true
599
+ }
600
+ },
601
+ pointerEnter: {
602
+ EventType: 'PointerEvent',
603
+ defaultInit: {
604
+ bubbles: false,
605
+ cancelable: false
606
+ }
607
+ },
608
+ pointerDown: {
609
+ EventType: 'PointerEvent',
610
+ defaultInit: {
611
+ bubbles: true,
612
+ cancelable: true,
613
+ composed: true
614
+ }
615
+ },
616
+ pointerMove: {
617
+ EventType: 'PointerEvent',
618
+ defaultInit: {
619
+ bubbles: true,
620
+ cancelable: true,
621
+ composed: true
622
+ }
623
+ },
624
+ pointerUp: {
625
+ EventType: 'PointerEvent',
626
+ defaultInit: {
627
+ bubbles: true,
628
+ cancelable: true,
629
+ composed: true
630
+ }
631
+ },
632
+ pointerCancel: {
633
+ EventType: 'PointerEvent',
634
+ defaultInit: {
635
+ bubbles: true,
636
+ cancelable: false,
637
+ composed: true
638
+ }
639
+ },
640
+ pointerOut: {
641
+ EventType: 'PointerEvent',
642
+ defaultInit: {
643
+ bubbles: true,
644
+ cancelable: true,
645
+ composed: true
646
+ }
647
+ },
648
+ pointerLeave: {
649
+ EventType: 'PointerEvent',
650
+ defaultInit: {
651
+ bubbles: false,
652
+ cancelable: false
653
+ }
654
+ },
655
+ gotPointerCapture: {
656
+ EventType: 'PointerEvent',
657
+ defaultInit: {
658
+ bubbles: true,
659
+ cancelable: false,
660
+ composed: true
661
+ }
662
+ },
663
+ lostPointerCapture: {
664
+ EventType: 'PointerEvent',
665
+ defaultInit: {
666
+ bubbles: true,
667
+ cancelable: false,
668
+ composed: true
669
+ }
670
+ },
671
+ // history events
672
+ popState: {
673
+ EventType: 'PopStateEvent',
674
+ defaultInit: {
675
+ bubbles: true,
676
+ cancelable: false
677
+ }
678
+ },
679
+ // window events
680
+ offline: {
681
+ EventType: 'Event',
682
+ defaultInit: {
683
+ bubbles: false,
684
+ cancelable: false
685
+ }
686
+ },
687
+ online: {
688
+ EventType: 'Event',
689
+ defaultInit: {
690
+ bubbles: false,
691
+ cancelable: false
692
+ }
693
+ },
694
+ pageHide: {
695
+ EventType: 'PageTransitionEvent',
696
+ defaultInit: {
697
+ bubbles: true,
698
+ cancelable: true
699
+ }
700
+ },
701
+ pageShow: {
702
+ EventType: 'PageTransitionEvent',
703
+ defaultInit: {
704
+ bubbles: true,
705
+ cancelable: true
706
+ }
707
+ }
708
+ };
709
+ const eventAliasMap = exports.eventAliasMap = {
710
+ doubleClick: 'dblClick'
711
+ };
node_modules/@testing-library/dom/dist/events.js ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createEvent = createEvent;
7
+ exports.fireEvent = fireEvent;
8
+ var _config = require("./config");
9
+ var _helpers = require("./helpers");
10
+ var _eventMap = require("./event-map");
11
+ function fireEvent(element, event) {
12
+ return (0, _config.getConfig)().eventWrapper(() => {
13
+ if (!event) {
14
+ throw new Error(`Unable to fire an event - please provide an event object.`);
15
+ }
16
+ if (!element) {
17
+ throw new Error(`Unable to fire a "${event.type}" event - please provide a DOM element.`);
18
+ }
19
+ return element.dispatchEvent(event);
20
+ });
21
+ }
22
+ function createEvent(eventName, node, init, {
23
+ EventType = 'Event',
24
+ defaultInit = {}
25
+ } = {}) {
26
+ if (!node) {
27
+ throw new Error(`Unable to fire a "${eventName}" event - please provide a DOM element.`);
28
+ }
29
+ const eventInit = {
30
+ ...defaultInit,
31
+ ...init
32
+ };
33
+ const {
34
+ target: {
35
+ value,
36
+ files,
37
+ ...targetProperties
38
+ } = {}
39
+ } = eventInit;
40
+ if (value !== undefined) {
41
+ setNativeValue(node, value);
42
+ }
43
+ if (files !== undefined) {
44
+ // input.files is a read-only property so this is not allowed:
45
+ // input.files = [file]
46
+ // so we have to use this workaround to set the property
47
+ Object.defineProperty(node, 'files', {
48
+ configurable: true,
49
+ enumerable: true,
50
+ writable: true,
51
+ value: files
52
+ });
53
+ }
54
+ Object.assign(node, targetProperties);
55
+ const window = (0, _helpers.getWindowFromNode)(node);
56
+ const EventConstructor = window[EventType] || window.Event;
57
+ let event;
58
+ /* istanbul ignore else */
59
+ if (typeof EventConstructor === 'function') {
60
+ event = new EventConstructor(eventName, eventInit);
61
+ } else {
62
+ // IE11 polyfill from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
63
+ event = window.document.createEvent(EventType);
64
+ const {
65
+ bubbles,
66
+ cancelable,
67
+ detail,
68
+ ...otherInit
69
+ } = eventInit;
70
+ event.initEvent(eventName, bubbles, cancelable, detail);
71
+ Object.keys(otherInit).forEach(eventKey => {
72
+ event[eventKey] = otherInit[eventKey];
73
+ });
74
+ }
75
+
76
+ // DataTransfer is not supported in jsdom: https://github.com/jsdom/jsdom/issues/1568
77
+ const dataTransferProperties = ['dataTransfer', 'clipboardData'];
78
+ dataTransferProperties.forEach(dataTransferKey => {
79
+ const dataTransferValue = eventInit[dataTransferKey];
80
+ if (typeof dataTransferValue === 'object') {
81
+ /* istanbul ignore if */
82
+ if (typeof window.DataTransfer === 'function') {
83
+ Object.defineProperty(event, dataTransferKey, {
84
+ value: Object.getOwnPropertyNames(dataTransferValue).reduce((acc, propName) => {
85
+ Object.defineProperty(acc, propName, {
86
+ value: dataTransferValue[propName]
87
+ });
88
+ return acc;
89
+ }, new window.DataTransfer())
90
+ });
91
+ } else {
92
+ Object.defineProperty(event, dataTransferKey, {
93
+ value: dataTransferValue
94
+ });
95
+ }
96
+ }
97
+ });
98
+ return event;
99
+ }
100
+ Object.keys(_eventMap.eventMap).forEach(key => {
101
+ const {
102
+ EventType,
103
+ defaultInit
104
+ } = _eventMap.eventMap[key];
105
+ const eventName = key.toLowerCase();
106
+ createEvent[key] = (node, init) => createEvent(eventName, node, init, {
107
+ EventType,
108
+ defaultInit
109
+ });
110
+ fireEvent[key] = (node, init) => fireEvent(node, createEvent[key](node, init));
111
+ });
112
+
113
+ // function written after some investigation here:
114
+ // https://github.com/facebook/react/issues/10135#issuecomment-401496776
115
+ function setNativeValue(element, value) {
116
+ const {
117
+ set: valueSetter
118
+ } = Object.getOwnPropertyDescriptor(element, 'value') || {};
119
+ const prototype = Object.getPrototypeOf(element);
120
+ const {
121
+ set: prototypeValueSetter
122
+ } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
123
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
124
+ prototypeValueSetter.call(element, value);
125
+ } else {
126
+ /* istanbul ignore if */
127
+ // eslint-disable-next-line no-lonely-if -- Can't be ignored by istanbul otherwise
128
+ if (valueSetter) {
129
+ valueSetter.call(element, value);
130
+ } else {
131
+ throw new Error('The given element does not have a value setter');
132
+ }
133
+ }
134
+ }
135
+ Object.keys(_eventMap.eventAliasMap).forEach(aliasKey => {
136
+ const key = _eventMap.eventAliasMap[aliasKey];
137
+ fireEvent[aliasKey] = (...args) => fireEvent[key](...args);
138
+ });
139
+
140
+ /* eslint complexity:["error", 9] */
node_modules/@testing-library/dom/dist/get-node-text.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getNodeText = getNodeText;
7
+ var _helpers = require("./helpers");
8
+ function getNodeText(node) {
9
+ if (node.matches('input[type=submit], input[type=button], input[type=reset]')) {
10
+ return node.value;
11
+ }
12
+ return Array.from(node.childNodes).filter(child => child.nodeType === _helpers.TEXT_NODE && Boolean(child.textContent)).map(c => c.textContent).join('');
13
+ }
node_modules/@testing-library/dom/dist/get-queries-for-element.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getQueriesForElement = getQueriesForElement;
7
+ var defaultQueries = _interopRequireWildcard(require("./queries"));
8
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
9
+ /**
10
+ * @typedef {{[key: string]: Function}} FuncMap
11
+ */
12
+
13
+ /**
14
+ * @param {HTMLElement} element container
15
+ * @param {FuncMap} queries object of functions
16
+ * @param {Object} initialValue for reducer
17
+ * @returns {FuncMap} returns object of functions bound to container
18
+ */
19
+ function getQueriesForElement(element, queries = defaultQueries, initialValue = {}) {
20
+ return Object.keys(queries).reduce((helpers, key) => {
21
+ const fn = queries[key];
22
+ helpers[key] = fn.bind(null, element);
23
+ return helpers;
24
+ }, initialValue);
25
+ }
node_modules/@testing-library/dom/dist/get-user-code-frame.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getUserCodeFrame = getUserCodeFrame;
7
+ // We try to load node dependencies
8
+ let picocolors = null;
9
+ let readFileSync = null;
10
+ let codeFrameColumns = null;
11
+ try {
12
+ const nodeRequire = module && module.require;
13
+ readFileSync = nodeRequire.call(module, 'fs').readFileSync;
14
+ codeFrameColumns = nodeRequire.call(module, '@babel/code-frame').codeFrameColumns;
15
+ picocolors = nodeRequire.call(module, 'picocolors');
16
+ } catch {
17
+ // We're in a browser environment
18
+ }
19
+
20
+ // frame has the form "at myMethod (location/to/my/file.js:10:2)"
21
+ function getCodeFrame(frame) {
22
+ const locationStart = frame.indexOf('(') + 1;
23
+ const locationEnd = frame.indexOf(')');
24
+ const frameLocation = frame.slice(locationStart, locationEnd);
25
+ const frameLocationElements = frameLocation.split(':');
26
+ const [filename, line, column] = [frameLocationElements[0], parseInt(frameLocationElements[1], 10), parseInt(frameLocationElements[2], 10)];
27
+ let rawFileContents = '';
28
+ try {
29
+ rawFileContents = readFileSync(filename, 'utf-8');
30
+ } catch {
31
+ return '';
32
+ }
33
+ const codeFrame = codeFrameColumns(rawFileContents, {
34
+ start: {
35
+ line,
36
+ column
37
+ }
38
+ }, {
39
+ highlightCode: true,
40
+ linesBelow: 0
41
+ });
42
+ return `${picocolors.dim(frameLocation)}\n${codeFrame}\n`;
43
+ }
44
+ function getUserCodeFrame() {
45
+ // If we couldn't load dependencies, we can't generate the user trace
46
+ /* istanbul ignore next */
47
+ if (!readFileSync || !codeFrameColumns) {
48
+ return '';
49
+ }
50
+ const err = new Error();
51
+ const firstClientCodeFrame = err.stack.split('\n').slice(1) // Remove first line which has the form "Error: TypeError"
52
+ .find(frame => !frame.includes('node_modules/')); // Ignore frames from 3rd party libraries
53
+
54
+ return getCodeFrame(firstClientCodeFrame);
55
+ }
node_modules/@testing-library/dom/dist/helpers.js ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.TEXT_NODE = void 0;
7
+ exports.checkContainerType = checkContainerType;
8
+ exports.getDocument = getDocument;
9
+ exports.getWindowFromNode = getWindowFromNode;
10
+ exports.jestFakeTimersAreEnabled = jestFakeTimersAreEnabled;
11
+ // Constant node.nodeType for text nodes, see:
12
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#Node_type_constants
13
+ const TEXT_NODE = exports.TEXT_NODE = 3;
14
+ function jestFakeTimersAreEnabled() {
15
+ /* istanbul ignore else */
16
+ // eslint-disable-next-line
17
+ if (typeof jest !== 'undefined' && jest !== null) {
18
+ return (
19
+ // legacy timers
20
+ setTimeout._isMockFunction === true ||
21
+ // modern timers
22
+ // eslint-disable-next-line prefer-object-has-own -- not supported by our support matrix
23
+ Object.prototype.hasOwnProperty.call(setTimeout, 'clock')
24
+ );
25
+ }
26
+ // istanbul ignore next
27
+ return false;
28
+ }
29
+ function getDocument() {
30
+ /* istanbul ignore if */
31
+ if (typeof window === 'undefined') {
32
+ throw new Error('Could not find default container');
33
+ }
34
+ return window.document;
35
+ }
36
+ function getWindowFromNode(node) {
37
+ if (node.defaultView) {
38
+ // node is document
39
+ return node.defaultView;
40
+ } else if (node.ownerDocument && node.ownerDocument.defaultView) {
41
+ // node is a DOM node
42
+ return node.ownerDocument.defaultView;
43
+ } else if (node.window) {
44
+ // node is window
45
+ return node.window;
46
+ } else if (node.ownerDocument && node.ownerDocument.defaultView === null) {
47
+ throw new Error(`It looks like the window object is not available for the provided node.`);
48
+ } else if (node.then instanceof Function) {
49
+ throw new Error(`It looks like you passed a Promise object instead of a DOM node. Did you do something like \`fireEvent.click(screen.findBy...\` when you meant to use a \`getBy\` query \`fireEvent.click(screen.getBy...\`, or await the findBy query \`fireEvent.click(await screen.findBy...\`?`);
50
+ } else if (Array.isArray(node)) {
51
+ throw new Error(`It looks like you passed an Array instead of a DOM node. Did you do something like \`fireEvent.click(screen.getAllBy...\` when you meant to use a \`getBy\` query \`fireEvent.click(screen.getBy...\`?`);
52
+ } else if (typeof node.debug === 'function' && typeof node.logTestingPlaygroundURL === 'function') {
53
+ throw new Error(`It looks like you passed a \`screen\` object. Did you do something like \`fireEvent.click(screen, ...\` when you meant to use a query, e.g. \`fireEvent.click(screen.getBy..., \`?`);
54
+ } else {
55
+ // The user passed something unusual to a calling function
56
+ throw new Error(`The given node is not an Element, the node type is: ${typeof node}.`);
57
+ }
58
+ }
59
+ function checkContainerType(container) {
60
+ if (!container || !(typeof container.querySelector === 'function') || !(typeof container.querySelectorAll === 'function')) {
61
+ throw new TypeError(`Expected container to be an Element, a Document or a DocumentFragment but got ${getTypeName(container)}.`);
62
+ }
63
+ function getTypeName(object) {
64
+ if (typeof object === 'object') {
65
+ return object === null ? 'null' : object.constructor.name;
66
+ }
67
+ return typeof object;
68
+ }
69
+ }
node_modules/@testing-library/dom/dist/index.js ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _exportNames = {
7
+ within: true,
8
+ queries: true,
9
+ queryHelpers: true,
10
+ getDefaultNormalizer: true,
11
+ getRoles: true,
12
+ logRoles: true,
13
+ isInaccessible: true,
14
+ configure: true,
15
+ getConfig: true
16
+ };
17
+ Object.defineProperty(exports, "configure", {
18
+ enumerable: true,
19
+ get: function () {
20
+ return _config.configure;
21
+ }
22
+ });
23
+ Object.defineProperty(exports, "getConfig", {
24
+ enumerable: true,
25
+ get: function () {
26
+ return _config.getConfig;
27
+ }
28
+ });
29
+ Object.defineProperty(exports, "getDefaultNormalizer", {
30
+ enumerable: true,
31
+ get: function () {
32
+ return _matches.getDefaultNormalizer;
33
+ }
34
+ });
35
+ Object.defineProperty(exports, "getRoles", {
36
+ enumerable: true,
37
+ get: function () {
38
+ return _roleHelpers.getRoles;
39
+ }
40
+ });
41
+ Object.defineProperty(exports, "isInaccessible", {
42
+ enumerable: true,
43
+ get: function () {
44
+ return _roleHelpers.isInaccessible;
45
+ }
46
+ });
47
+ Object.defineProperty(exports, "logRoles", {
48
+ enumerable: true,
49
+ get: function () {
50
+ return _roleHelpers.logRoles;
51
+ }
52
+ });
53
+ exports.queryHelpers = exports.queries = void 0;
54
+ Object.defineProperty(exports, "within", {
55
+ enumerable: true,
56
+ get: function () {
57
+ return _getQueriesForElement.getQueriesForElement;
58
+ }
59
+ });
60
+ var _getQueriesForElement = require("./get-queries-for-element");
61
+ Object.keys(_getQueriesForElement).forEach(function (key) {
62
+ if (key === "default" || key === "__esModule") return;
63
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
64
+ if (key in exports && exports[key] === _getQueriesForElement[key]) return;
65
+ Object.defineProperty(exports, key, {
66
+ enumerable: true,
67
+ get: function () {
68
+ return _getQueriesForElement[key];
69
+ }
70
+ });
71
+ });
72
+ var queries = _interopRequireWildcard(require("./queries"));
73
+ exports.queries = queries;
74
+ Object.keys(queries).forEach(function (key) {
75
+ if (key === "default" || key === "__esModule") return;
76
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
77
+ if (key in exports && exports[key] === queries[key]) return;
78
+ Object.defineProperty(exports, key, {
79
+ enumerable: true,
80
+ get: function () {
81
+ return queries[key];
82
+ }
83
+ });
84
+ });
85
+ var queryHelpers = _interopRequireWildcard(require("./query-helpers"));
86
+ exports.queryHelpers = queryHelpers;
87
+ Object.keys(queryHelpers).forEach(function (key) {
88
+ if (key === "default" || key === "__esModule") return;
89
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
90
+ if (key in exports && exports[key] === queryHelpers[key]) return;
91
+ Object.defineProperty(exports, key, {
92
+ enumerable: true,
93
+ get: function () {
94
+ return queryHelpers[key];
95
+ }
96
+ });
97
+ });
98
+ var _waitFor = require("./wait-for");
99
+ Object.keys(_waitFor).forEach(function (key) {
100
+ if (key === "default" || key === "__esModule") return;
101
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
102
+ if (key in exports && exports[key] === _waitFor[key]) return;
103
+ Object.defineProperty(exports, key, {
104
+ enumerable: true,
105
+ get: function () {
106
+ return _waitFor[key];
107
+ }
108
+ });
109
+ });
110
+ var _waitForElementToBeRemoved = require("./wait-for-element-to-be-removed");
111
+ Object.keys(_waitForElementToBeRemoved).forEach(function (key) {
112
+ if (key === "default" || key === "__esModule") return;
113
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
114
+ if (key in exports && exports[key] === _waitForElementToBeRemoved[key]) return;
115
+ Object.defineProperty(exports, key, {
116
+ enumerable: true,
117
+ get: function () {
118
+ return _waitForElementToBeRemoved[key];
119
+ }
120
+ });
121
+ });
122
+ var _matches = require("./matches");
123
+ var _getNodeText = require("./get-node-text");
124
+ Object.keys(_getNodeText).forEach(function (key) {
125
+ if (key === "default" || key === "__esModule") return;
126
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
127
+ if (key in exports && exports[key] === _getNodeText[key]) return;
128
+ Object.defineProperty(exports, key, {
129
+ enumerable: true,
130
+ get: function () {
131
+ return _getNodeText[key];
132
+ }
133
+ });
134
+ });
135
+ var _events = require("./events");
136
+ Object.keys(_events).forEach(function (key) {
137
+ if (key === "default" || key === "__esModule") return;
138
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
139
+ if (key in exports && exports[key] === _events[key]) return;
140
+ Object.defineProperty(exports, key, {
141
+ enumerable: true,
142
+ get: function () {
143
+ return _events[key];
144
+ }
145
+ });
146
+ });
147
+ var _screen = require("./screen");
148
+ Object.keys(_screen).forEach(function (key) {
149
+ if (key === "default" || key === "__esModule") return;
150
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
151
+ if (key in exports && exports[key] === _screen[key]) return;
152
+ Object.defineProperty(exports, key, {
153
+ enumerable: true,
154
+ get: function () {
155
+ return _screen[key];
156
+ }
157
+ });
158
+ });
159
+ var _roleHelpers = require("./role-helpers");
160
+ var _prettyDom = require("./pretty-dom");
161
+ Object.keys(_prettyDom).forEach(function (key) {
162
+ if (key === "default" || key === "__esModule") return;
163
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
164
+ if (key in exports && exports[key] === _prettyDom[key]) return;
165
+ Object.defineProperty(exports, key, {
166
+ enumerable: true,
167
+ get: function () {
168
+ return _prettyDom[key];
169
+ }
170
+ });
171
+ });
172
+ var _config = require("./config");
173
+ var _suggestions = require("./suggestions");
174
+ Object.keys(_suggestions).forEach(function (key) {
175
+ if (key === "default" || key === "__esModule") return;
176
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
177
+ if (key in exports && exports[key] === _suggestions[key]) return;
178
+ Object.defineProperty(exports, key, {
179
+ enumerable: true,
180
+ get: function () {
181
+ return _suggestions[key];
182
+ }
183
+ });
184
+ });
185
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
node_modules/@testing-library/dom/dist/label-helpers.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getLabelContent = getLabelContent;
7
+ exports.getLabels = getLabels;
8
+ exports.getRealLabels = getRealLabels;
9
+ var _helpers = require("./helpers");
10
+ const labelledNodeNames = ['button', 'meter', 'output', 'progress', 'select', 'textarea', 'input'];
11
+ function getTextContent(node) {
12
+ if (labelledNodeNames.includes(node.nodeName.toLowerCase())) {
13
+ return '';
14
+ }
15
+ if (node.nodeType === _helpers.TEXT_NODE) return node.textContent;
16
+ return Array.from(node.childNodes).map(childNode => getTextContent(childNode)).join('');
17
+ }
18
+ function getLabelContent(element) {
19
+ let textContent;
20
+ if (element.tagName.toLowerCase() === 'label') {
21
+ textContent = getTextContent(element);
22
+ } else {
23
+ textContent = element.value || element.textContent;
24
+ }
25
+ return textContent;
26
+ }
27
+
28
+ // Based on https://github.com/eps1lon/dom-accessibility-api/pull/352
29
+ function getRealLabels(element) {
30
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- types are not aware of older browsers that don't implement `labels`
31
+ if (element.labels !== undefined) {
32
+ return element.labels ?? [];
33
+ }
34
+ if (!isLabelable(element)) return [];
35
+ const labels = element.ownerDocument.querySelectorAll('label');
36
+ return Array.from(labels).filter(label => label.control === element);
37
+ }
38
+ function isLabelable(element) {
39
+ return /BUTTON|METER|OUTPUT|PROGRESS|SELECT|TEXTAREA/.test(element.tagName) || element.tagName === 'INPUT' && element.getAttribute('type') !== 'hidden';
40
+ }
41
+ function getLabels(container, element, {
42
+ selector = '*'
43
+ } = {}) {
44
+ const ariaLabelledBy = element.getAttribute('aria-labelledby');
45
+ const labelsId = ariaLabelledBy ? ariaLabelledBy.split(' ') : [];
46
+ return labelsId.length ? labelsId.map(labelId => {
47
+ const labellingElement = container.querySelector(`[id="${labelId}"]`);
48
+ return labellingElement ? {
49
+ content: getLabelContent(labellingElement),
50
+ formControl: null
51
+ } : {
52
+ content: '',
53
+ formControl: null
54
+ };
55
+ }) : Array.from(getRealLabels(element)).map(label => {
56
+ const textToMatch = getLabelContent(label);
57
+ const formControlSelector = 'button, input, meter, output, progress, select, textarea';
58
+ const labelledFormControl = Array.from(label.querySelectorAll(formControlSelector)).filter(formControlElement => formControlElement.matches(selector))[0];
59
+ return {
60
+ content: textToMatch,
61
+ formControl: labelledFormControl
62
+ };
63
+ });
64
+ }
node_modules/@testing-library/dom/dist/matches.js ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.fuzzyMatches = fuzzyMatches;
7
+ exports.getDefaultNormalizer = getDefaultNormalizer;
8
+ exports.makeNormalizer = makeNormalizer;
9
+ exports.matches = matches;
10
+ function assertNotNullOrUndefined(matcher) {
11
+ if (matcher === null || matcher === undefined) {
12
+ throw new Error(
13
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- implicitly converting `T` to `string`
14
+ `It looks like ${matcher} was passed instead of a matcher. Did you do something like getByText(${matcher})?`);
15
+ }
16
+ }
17
+ function fuzzyMatches(textToMatch, node, matcher, normalizer) {
18
+ if (typeof textToMatch !== 'string') {
19
+ return false;
20
+ }
21
+ assertNotNullOrUndefined(matcher);
22
+ const normalizedText = normalizer(textToMatch);
23
+ if (typeof matcher === 'string' || typeof matcher === 'number') {
24
+ return normalizedText.toLowerCase().includes(matcher.toString().toLowerCase());
25
+ } else if (typeof matcher === 'function') {
26
+ return matcher(normalizedText, node);
27
+ } else {
28
+ return matchRegExp(matcher, normalizedText);
29
+ }
30
+ }
31
+ function matches(textToMatch, node, matcher, normalizer) {
32
+ if (typeof textToMatch !== 'string') {
33
+ return false;
34
+ }
35
+ assertNotNullOrUndefined(matcher);
36
+ const normalizedText = normalizer(textToMatch);
37
+ if (matcher instanceof Function) {
38
+ return matcher(normalizedText, node);
39
+ } else if (matcher instanceof RegExp) {
40
+ return matchRegExp(matcher, normalizedText);
41
+ } else {
42
+ return normalizedText === String(matcher);
43
+ }
44
+ }
45
+ function getDefaultNormalizer({
46
+ trim = true,
47
+ collapseWhitespace = true
48
+ } = {}) {
49
+ return text => {
50
+ let normalizedText = text;
51
+ normalizedText = trim ? normalizedText.trim() : normalizedText;
52
+ normalizedText = collapseWhitespace ? normalizedText.replace(/\s+/g, ' ') : normalizedText;
53
+ return normalizedText;
54
+ };
55
+ }
56
+
57
+ /**
58
+ * Constructs a normalizer to pass to functions in matches.js
59
+ * @param {boolean|undefined} trim The user-specified value for `trim`, without
60
+ * any defaulting having been applied
61
+ * @param {boolean|undefined} collapseWhitespace The user-specified value for
62
+ * `collapseWhitespace`, without any defaulting having been applied
63
+ * @param {Function|undefined} normalizer The user-specified normalizer
64
+ * @returns {Function} A normalizer
65
+ */
66
+
67
+ function makeNormalizer({
68
+ trim,
69
+ collapseWhitespace,
70
+ normalizer
71
+ }) {
72
+ if (!normalizer) {
73
+ // No custom normalizer specified. Just use default.
74
+ return getDefaultNormalizer({
75
+ trim,
76
+ collapseWhitespace
77
+ });
78
+ }
79
+ if (typeof trim !== 'undefined' || typeof collapseWhitespace !== 'undefined') {
80
+ // They've also specified a value for trim or collapseWhitespace
81
+ throw new Error('trim and collapseWhitespace are not supported with a normalizer. ' + 'If you want to use the default trim and collapseWhitespace logic in your normalizer, ' + 'use "getDefaultNormalizer({trim, collapseWhitespace})" and compose that into your normalizer');
82
+ }
83
+ return normalizer;
84
+ }
85
+ function matchRegExp(matcher, text) {
86
+ const match = matcher.test(text);
87
+ if (matcher.global && matcher.lastIndex !== 0) {
88
+ console.warn(`To match all elements we had to reset the lastIndex of the RegExp because the global flag is enabled. We encourage to remove the global flag from the RegExp.`);
89
+ matcher.lastIndex = 0;
90
+ }
91
+ return match;
92
+ }
node_modules/@testing-library/dom/dist/pretty-dom.js ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.logDOM = void 0;
8
+ exports.prettyDOM = prettyDOM;
9
+ exports.prettyFormat = void 0;
10
+ var prettyFormat = _interopRequireWildcard(require("pretty-format"));
11
+ exports.prettyFormat = prettyFormat;
12
+ var _DOMElementFilter = _interopRequireDefault(require("./DOMElementFilter"));
13
+ var _getUserCodeFrame = require("./get-user-code-frame");
14
+ var _helpers = require("./helpers");
15
+ var _config = require("./config");
16
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
17
+ const shouldHighlight = () => {
18
+ if (typeof process === 'undefined') {
19
+ // Don't colorize in non-node environments (e.g. Browsers)
20
+ return false;
21
+ }
22
+ let colors;
23
+ // Try to safely parse env COLORS: We will default behavior if any step fails.
24
+ try {
25
+ const colorsJSON = process.env?.COLORS;
26
+ if (colorsJSON) {
27
+ colors = JSON.parse(colorsJSON);
28
+ }
29
+ } catch {
30
+ // If this throws, process.env?.COLORS wasn't parsable. Since we only
31
+ // care about `true` or `false`, we can safely ignore the error.
32
+ }
33
+ if (typeof colors === 'boolean') {
34
+ // If `colors` is set explicitly (both `true` and `false`), use that value.
35
+ return colors;
36
+ } else {
37
+ // If `colors` is not set, colorize if we're in node.
38
+ return process.versions !== undefined && process.versions.node !== undefined;
39
+ }
40
+ };
41
+ const {
42
+ DOMCollection
43
+ } = prettyFormat.plugins;
44
+
45
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#node_type_constants
46
+ const ELEMENT_NODE = 1;
47
+ const COMMENT_NODE = 8;
48
+
49
+ // https://github.com/facebook/jest/blob/615084195ae1ae61ddd56162c62bbdda17587569/packages/pretty-format/src/plugins/DOMElement.ts#L50
50
+ function filterCommentsAndDefaultIgnoreTagsTags(value) {
51
+ return value.nodeType !== COMMENT_NODE && (value.nodeType !== ELEMENT_NODE || !value.matches((0, _config.getConfig)().defaultIgnore));
52
+ }
53
+ function prettyDOM(dom, maxLength, options = {}) {
54
+ if (!dom) {
55
+ dom = (0, _helpers.getDocument)().body;
56
+ }
57
+ if (typeof maxLength !== 'number') {
58
+ maxLength = typeof process !== 'undefined' && typeof process.env !== 'undefined' && process.env.DEBUG_PRINT_LIMIT || 7000;
59
+ }
60
+ if (maxLength === 0) {
61
+ return '';
62
+ }
63
+ if (dom.documentElement) {
64
+ dom = dom.documentElement;
65
+ }
66
+ let domTypeName = typeof dom;
67
+ if (domTypeName === 'object') {
68
+ domTypeName = dom.constructor.name;
69
+ } else {
70
+ // To don't fall with `in` operator
71
+ dom = {};
72
+ }
73
+ if (!('outerHTML' in dom)) {
74
+ throw new TypeError(`Expected an element or document but got ${domTypeName}`);
75
+ }
76
+ const {
77
+ filterNode = filterCommentsAndDefaultIgnoreTagsTags,
78
+ ...prettyFormatOptions
79
+ } = options;
80
+ const debugContent = prettyFormat.format(dom, {
81
+ plugins: [(0, _DOMElementFilter.default)(filterNode), DOMCollection],
82
+ printFunctionName: false,
83
+ highlight: shouldHighlight(),
84
+ ...prettyFormatOptions
85
+ });
86
+ return maxLength !== undefined && dom.outerHTML.length > maxLength ? `${debugContent.slice(0, maxLength)}...` : debugContent;
87
+ }
88
+ const logDOM = (...args) => {
89
+ const userCodeFrame = (0, _getUserCodeFrame.getUserCodeFrame)();
90
+ if (userCodeFrame) {
91
+ console.log(`${prettyDOM(...args)}\n\n${userCodeFrame}`);
92
+ } else {
93
+ console.log(prettyDOM(...args));
94
+ }
95
+ };
96
+ exports.logDOM = logDOM;
node_modules/@testing-library/dom/dist/queries/all-utils.js ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _matches = require("../matches");
7
+ Object.keys(_matches).forEach(function (key) {
8
+ if (key === "default" || key === "__esModule") return;
9
+ if (key in exports && exports[key] === _matches[key]) return;
10
+ Object.defineProperty(exports, key, {
11
+ enumerable: true,
12
+ get: function () {
13
+ return _matches[key];
14
+ }
15
+ });
16
+ });
17
+ var _getNodeText = require("../get-node-text");
18
+ Object.keys(_getNodeText).forEach(function (key) {
19
+ if (key === "default" || key === "__esModule") return;
20
+ if (key in exports && exports[key] === _getNodeText[key]) return;
21
+ Object.defineProperty(exports, key, {
22
+ enumerable: true,
23
+ get: function () {
24
+ return _getNodeText[key];
25
+ }
26
+ });
27
+ });
28
+ var _queryHelpers = require("../query-helpers");
29
+ Object.keys(_queryHelpers).forEach(function (key) {
30
+ if (key === "default" || key === "__esModule") return;
31
+ if (key in exports && exports[key] === _queryHelpers[key]) return;
32
+ Object.defineProperty(exports, key, {
33
+ enumerable: true,
34
+ get: function () {
35
+ return _queryHelpers[key];
36
+ }
37
+ });
38
+ });
39
+ var _config = require("../config");
40
+ Object.keys(_config).forEach(function (key) {
41
+ if (key === "default" || key === "__esModule") return;
42
+ if (key in exports && exports[key] === _config[key]) return;
43
+ Object.defineProperty(exports, key, {
44
+ enumerable: true,
45
+ get: function () {
46
+ return _config[key];
47
+ }
48
+ });
49
+ });
node_modules/@testing-library/dom/dist/queries/alt-text.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.queryByAltText = exports.queryAllByAltText = exports.getByAltText = exports.getAllByAltText = exports.findByAltText = exports.findAllByAltText = void 0;
7
+ var _queryHelpers = require("../query-helpers");
8
+ var _helpers = require("../helpers");
9
+ var _allUtils = require("./all-utils");
10
+ // Valid tags are img, input, area and custom elements
11
+ const VALID_TAG_REGEXP = /^(img|input|area|.+-.+)$/i;
12
+ const queryAllByAltText = (container, alt, options = {}) => {
13
+ (0, _helpers.checkContainerType)(container);
14
+ return (0, _queryHelpers.queryAllByAttribute)('alt', container, alt, options).filter(node => VALID_TAG_REGEXP.test(node.tagName));
15
+ };
16
+ const getMultipleError = (c, alt) => `Found multiple elements with the alt text: ${alt}`;
17
+ const getMissingError = (c, alt) => `Unable to find an element with the alt text: ${alt}`;
18
+ const queryAllByAltTextWithSuggestions = exports.queryAllByAltText = (0, _queryHelpers.wrapAllByQueryWithSuggestion)(queryAllByAltText, queryAllByAltText.name, 'queryAll');
19
+ const [queryByAltText, getAllByAltText, getByAltText, findAllByAltText, findByAltText] = (0, _allUtils.buildQueries)(queryAllByAltText, getMultipleError, getMissingError);
20
+ exports.findByAltText = findByAltText;
21
+ exports.findAllByAltText = findAllByAltText;
22
+ exports.getByAltText = getByAltText;
23
+ exports.getAllByAltText = getAllByAltText;
24
+ exports.queryByAltText = queryByAltText;
node_modules/@testing-library/dom/dist/queries/display-value.js ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.queryByDisplayValue = exports.queryAllByDisplayValue = exports.getByDisplayValue = exports.getAllByDisplayValue = exports.findByDisplayValue = exports.findAllByDisplayValue = void 0;
7
+ var _queryHelpers = require("../query-helpers");
8
+ var _helpers = require("../helpers");
9
+ var _allUtils = require("./all-utils");
10
+ const queryAllByDisplayValue = (container, value, {
11
+ exact = true,
12
+ collapseWhitespace,
13
+ trim,
14
+ normalizer
15
+ } = {}) => {
16
+ (0, _helpers.checkContainerType)(container);
17
+ const matcher = exact ? _allUtils.matches : _allUtils.fuzzyMatches;
18
+ const matchNormalizer = (0, _allUtils.makeNormalizer)({
19
+ collapseWhitespace,
20
+ trim,
21
+ normalizer
22
+ });
23
+ return Array.from(container.querySelectorAll(`input,textarea,select`)).filter(node => {
24
+ if (node.tagName === 'SELECT') {
25
+ const selectedOptions = Array.from(node.options).filter(option => option.selected);
26
+ return selectedOptions.some(optionNode => matcher((0, _allUtils.getNodeText)(optionNode), optionNode, value, matchNormalizer));
27
+ } else {
28
+ return matcher(node.value, node, value, matchNormalizer);
29
+ }
30
+ });
31
+ };
32
+ const getMultipleError = (c, value) => `Found multiple elements with the display value: ${value}.`;
33
+ const getMissingError = (c, value) => `Unable to find an element with the display value: ${value}.`;
34
+ const queryAllByDisplayValueWithSuggestions = exports.queryAllByDisplayValue = (0, _queryHelpers.wrapAllByQueryWithSuggestion)(queryAllByDisplayValue, queryAllByDisplayValue.name, 'queryAll');
35
+ const [queryByDisplayValue, getAllByDisplayValue, getByDisplayValue, findAllByDisplayValue, findByDisplayValue] = (0, _allUtils.buildQueries)(queryAllByDisplayValue, getMultipleError, getMissingError);
36
+ exports.findByDisplayValue = findByDisplayValue;
37
+ exports.findAllByDisplayValue = findAllByDisplayValue;
38
+ exports.getByDisplayValue = getByDisplayValue;
39
+ exports.getAllByDisplayValue = getAllByDisplayValue;
40
+ exports.queryByDisplayValue = queryByDisplayValue;
node_modules/@testing-library/dom/dist/queries/index.js ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _labelText = require("./label-text");
7
+ Object.keys(_labelText).forEach(function (key) {
8
+ if (key === "default" || key === "__esModule") return;
9
+ if (key in exports && exports[key] === _labelText[key]) return;
10
+ Object.defineProperty(exports, key, {
11
+ enumerable: true,
12
+ get: function () {
13
+ return _labelText[key];
14
+ }
15
+ });
16
+ });
17
+ var _placeholderText = require("./placeholder-text");
18
+ Object.keys(_placeholderText).forEach(function (key) {
19
+ if (key === "default" || key === "__esModule") return;
20
+ if (key in exports && exports[key] === _placeholderText[key]) return;
21
+ Object.defineProperty(exports, key, {
22
+ enumerable: true,
23
+ get: function () {
24
+ return _placeholderText[key];
25
+ }
26
+ });
27
+ });
28
+ var _text = require("./text");
29
+ Object.keys(_text).forEach(function (key) {
30
+ if (key === "default" || key === "__esModule") return;
31
+ if (key in exports && exports[key] === _text[key]) return;
32
+ Object.defineProperty(exports, key, {
33
+ enumerable: true,
34
+ get: function () {
35
+ return _text[key];
36
+ }
37
+ });
38
+ });
39
+ var _displayValue = require("./display-value");
40
+ Object.keys(_displayValue).forEach(function (key) {
41
+ if (key === "default" || key === "__esModule") return;
42
+ if (key in exports && exports[key] === _displayValue[key]) return;
43
+ Object.defineProperty(exports, key, {
44
+ enumerable: true,
45
+ get: function () {
46
+ return _displayValue[key];
47
+ }
48
+ });
49
+ });
50
+ var _altText = require("./alt-text");
51
+ Object.keys(_altText).forEach(function (key) {
52
+ if (key === "default" || key === "__esModule") return;
53
+ if (key in exports && exports[key] === _altText[key]) return;
54
+ Object.defineProperty(exports, key, {
55
+ enumerable: true,
56
+ get: function () {
57
+ return _altText[key];
58
+ }
59
+ });
60
+ });
61
+ var _title = require("./title");
62
+ Object.keys(_title).forEach(function (key) {
63
+ if (key === "default" || key === "__esModule") return;
64
+ if (key in exports && exports[key] === _title[key]) return;
65
+ Object.defineProperty(exports, key, {
66
+ enumerable: true,
67
+ get: function () {
68
+ return _title[key];
69
+ }
70
+ });
71
+ });
72
+ var _role = require("./role");
73
+ Object.keys(_role).forEach(function (key) {
74
+ if (key === "default" || key === "__esModule") return;
75
+ if (key in exports && exports[key] === _role[key]) return;
76
+ Object.defineProperty(exports, key, {
77
+ enumerable: true,
78
+ get: function () {
79
+ return _role[key];
80
+ }
81
+ });
82
+ });
83
+ var _testId = require("./test-id");
84
+ Object.keys(_testId).forEach(function (key) {
85
+ if (key === "default" || key === "__esModule") return;
86
+ if (key in exports && exports[key] === _testId[key]) return;
87
+ Object.defineProperty(exports, key, {
88
+ enumerable: true,
89
+ get: function () {
90
+ return _testId[key];
91
+ }
92
+ });
93
+ });
node_modules/@testing-library/dom/dist/queries/label-text.js ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.queryByLabelText = exports.queryAllByLabelText = exports.getByLabelText = exports.getAllByLabelText = exports.findByLabelText = exports.findAllByLabelText = void 0;
7
+ var _config = require("../config");
8
+ var _helpers = require("../helpers");
9
+ var _labelHelpers = require("../label-helpers");
10
+ var _allUtils = require("./all-utils");
11
+ function queryAllLabels(container) {
12
+ return Array.from(container.querySelectorAll('label,input')).map(node => {
13
+ return {
14
+ node,
15
+ textToMatch: (0, _labelHelpers.getLabelContent)(node)
16
+ };
17
+ }).filter(({
18
+ textToMatch
19
+ }) => textToMatch !== null);
20
+ }
21
+ const queryAllLabelsByText = (container, text, {
22
+ exact = true,
23
+ trim,
24
+ collapseWhitespace,
25
+ normalizer
26
+ } = {}) => {
27
+ const matcher = exact ? _allUtils.matches : _allUtils.fuzzyMatches;
28
+ const matchNormalizer = (0, _allUtils.makeNormalizer)({
29
+ collapseWhitespace,
30
+ trim,
31
+ normalizer
32
+ });
33
+ const textToMatchByLabels = queryAllLabels(container);
34
+ return textToMatchByLabels.filter(({
35
+ node,
36
+ textToMatch
37
+ }) => matcher(textToMatch, node, text, matchNormalizer)).map(({
38
+ node
39
+ }) => node);
40
+ };
41
+ const queryAllByLabelText = (container, text, {
42
+ selector = '*',
43
+ exact = true,
44
+ collapseWhitespace,
45
+ trim,
46
+ normalizer
47
+ } = {}) => {
48
+ (0, _helpers.checkContainerType)(container);
49
+ const matcher = exact ? _allUtils.matches : _allUtils.fuzzyMatches;
50
+ const matchNormalizer = (0, _allUtils.makeNormalizer)({
51
+ collapseWhitespace,
52
+ trim,
53
+ normalizer
54
+ });
55
+ const matchingLabelledElements = Array.from(container.querySelectorAll('*')).filter(element => {
56
+ return (0, _labelHelpers.getRealLabels)(element).length || element.hasAttribute('aria-labelledby');
57
+ }).reduce((labelledElements, labelledElement) => {
58
+ const labelList = (0, _labelHelpers.getLabels)(container, labelledElement, {
59
+ selector
60
+ });
61
+ labelList.filter(label => Boolean(label.formControl)).forEach(label => {
62
+ if (matcher(label.content, label.formControl, text, matchNormalizer) && label.formControl) {
63
+ labelledElements.push(label.formControl);
64
+ }
65
+ });
66
+ const labelsValue = labelList.filter(label => Boolean(label.content)).map(label => label.content);
67
+ if (matcher(labelsValue.join(' '), labelledElement, text, matchNormalizer)) {
68
+ labelledElements.push(labelledElement);
69
+ }
70
+ if (labelsValue.length > 1) {
71
+ labelsValue.forEach((labelValue, index) => {
72
+ if (matcher(labelValue, labelledElement, text, matchNormalizer)) {
73
+ labelledElements.push(labelledElement);
74
+ }
75
+ const labelsFiltered = [...labelsValue];
76
+ labelsFiltered.splice(index, 1);
77
+ if (labelsFiltered.length > 1) {
78
+ if (matcher(labelsFiltered.join(' '), labelledElement, text, matchNormalizer)) {
79
+ labelledElements.push(labelledElement);
80
+ }
81
+ }
82
+ });
83
+ }
84
+ return labelledElements;
85
+ }, []).concat((0, _allUtils.queryAllByAttribute)('aria-label', container, text, {
86
+ exact,
87
+ normalizer: matchNormalizer
88
+ }));
89
+ return Array.from(new Set(matchingLabelledElements)).filter(element => element.matches(selector));
90
+ };
91
+
92
+ // the getAll* query would normally look like this:
93
+ // const getAllByLabelText = makeGetAllQuery(
94
+ // queryAllByLabelText,
95
+ // (c, text) => `Unable to find a label with the text of: ${text}`,
96
+ // )
97
+ // however, we can give a more helpful error message than the generic one,
98
+ // so we're writing this one out by hand.
99
+ const getAllByLabelText = (container, text, ...rest) => {
100
+ const els = queryAllByLabelText(container, text, ...rest);
101
+ if (!els.length) {
102
+ const labels = queryAllLabelsByText(container, text, ...rest);
103
+ if (labels.length) {
104
+ const tagNames = labels.map(label => getTagNameOfElementAssociatedWithLabelViaFor(container, label)).filter(tagName => !!tagName);
105
+ if (tagNames.length) {
106
+ throw (0, _config.getConfig)().getElementError(tagNames.map(tagName => `Found a label with the text of: ${text}, however the element associated with this label (<${tagName} />) is non-labellable [https://html.spec.whatwg.org/multipage/forms.html#category-label]. If you really need to label a <${tagName} />, you can use aria-label or aria-labelledby instead.`).join('\n\n'), container);
107
+ } else {
108
+ throw (0, _config.getConfig)().getElementError(`Found a label with the text of: ${text}, however no form control was found associated to that label. Make sure you're using the "for" attribute or "aria-labelledby" attribute correctly.`, container);
109
+ }
110
+ } else {
111
+ throw (0, _config.getConfig)().getElementError(`Unable to find a label with the text of: ${text}`, container);
112
+ }
113
+ }
114
+ return els;
115
+ };
116
+ function getTagNameOfElementAssociatedWithLabelViaFor(container, label) {
117
+ const htmlFor = label.getAttribute('for');
118
+ if (!htmlFor) {
119
+ return null;
120
+ }
121
+ const element = container.querySelector(`[id="${htmlFor}"]`);
122
+ return element ? element.tagName.toLowerCase() : null;
123
+ }
124
+
125
+ // the reason mentioned above is the same reason we're not using buildQueries
126
+ const getMultipleError = (c, text) => `Found multiple elements with the text of: ${text}`;
127
+ const queryByLabelText = exports.queryByLabelText = (0, _allUtils.wrapSingleQueryWithSuggestion)((0, _allUtils.makeSingleQuery)(queryAllByLabelText, getMultipleError), queryAllByLabelText.name, 'query');
128
+ const getByLabelText = (0, _allUtils.makeSingleQuery)(getAllByLabelText, getMultipleError);
129
+ const findAllByLabelText = exports.findAllByLabelText = (0, _allUtils.makeFindQuery)((0, _allUtils.wrapAllByQueryWithSuggestion)(getAllByLabelText, getAllByLabelText.name, 'findAll'));
130
+ const findByLabelText = exports.findByLabelText = (0, _allUtils.makeFindQuery)((0, _allUtils.wrapSingleQueryWithSuggestion)(getByLabelText, getAllByLabelText.name, 'find'));
131
+ const getAllByLabelTextWithSuggestions = exports.getAllByLabelText = (0, _allUtils.wrapAllByQueryWithSuggestion)(getAllByLabelText, getAllByLabelText.name, 'getAll');
132
+ const getByLabelTextWithSuggestions = exports.getByLabelText = (0, _allUtils.wrapSingleQueryWithSuggestion)(getByLabelText, getAllByLabelText.name, 'get');
133
+ const queryAllByLabelTextWithSuggestions = exports.queryAllByLabelText = (0, _allUtils.wrapAllByQueryWithSuggestion)(queryAllByLabelText, queryAllByLabelText.name, 'queryAll');
node_modules/@testing-library/dom/dist/queries/placeholder-text.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.queryByPlaceholderText = exports.queryAllByPlaceholderText = exports.getByPlaceholderText = exports.getAllByPlaceholderText = exports.findByPlaceholderText = exports.findAllByPlaceholderText = void 0;
7
+ var _queryHelpers = require("../query-helpers");
8
+ var _helpers = require("../helpers");
9
+ var _allUtils = require("./all-utils");
10
+ const queryAllByPlaceholderText = (...args) => {
11
+ (0, _helpers.checkContainerType)(args[0]);
12
+ return (0, _allUtils.queryAllByAttribute)('placeholder', ...args);
13
+ };
14
+ const getMultipleError = (c, text) => `Found multiple elements with the placeholder text of: ${text}`;
15
+ const getMissingError = (c, text) => `Unable to find an element with the placeholder text of: ${text}`;
16
+ const queryAllByPlaceholderTextWithSuggestions = exports.queryAllByPlaceholderText = (0, _queryHelpers.wrapAllByQueryWithSuggestion)(queryAllByPlaceholderText, queryAllByPlaceholderText.name, 'queryAll');
17
+ const [queryByPlaceholderText, getAllByPlaceholderText, getByPlaceholderText, findAllByPlaceholderText, findByPlaceholderText] = (0, _allUtils.buildQueries)(queryAllByPlaceholderText, getMultipleError, getMissingError);
18
+ exports.findByPlaceholderText = findByPlaceholderText;
19
+ exports.findAllByPlaceholderText = findAllByPlaceholderText;
20
+ exports.getByPlaceholderText = getByPlaceholderText;
21
+ exports.getAllByPlaceholderText = getAllByPlaceholderText;
22
+ exports.queryByPlaceholderText = queryByPlaceholderText;
node_modules/@testing-library/dom/dist/queries/role.js ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.queryByRole = exports.queryAllByRole = exports.getByRole = exports.getAllByRole = exports.findByRole = exports.findAllByRole = void 0;
7
+ var _domAccessibilityApi = require("dom-accessibility-api");
8
+ var _ariaQuery = require("aria-query");
9
+ var _roleHelpers = require("../role-helpers");
10
+ var _queryHelpers = require("../query-helpers");
11
+ var _helpers = require("../helpers");
12
+ var _allUtils = require("./all-utils");
13
+ /* eslint-disable complexity */
14
+
15
+ const queryAllByRole = (container, role, {
16
+ hidden = (0, _allUtils.getConfig)().defaultHidden,
17
+ name,
18
+ description,
19
+ queryFallbacks = false,
20
+ selected,
21
+ busy,
22
+ checked,
23
+ pressed,
24
+ current,
25
+ level,
26
+ expanded,
27
+ value: {
28
+ now: valueNow,
29
+ min: valueMin,
30
+ max: valueMax,
31
+ text: valueText
32
+ } = {}
33
+ } = {}) => {
34
+ (0, _helpers.checkContainerType)(container);
35
+ if (selected !== undefined) {
36
+ // guard against unknown roles
37
+ if (_ariaQuery.roles.get(role)?.props['aria-selected'] === undefined) {
38
+ throw new Error(`"aria-selected" is not supported on role "${role}".`);
39
+ }
40
+ }
41
+ if (busy !== undefined) {
42
+ // guard against unknown roles
43
+ if (_ariaQuery.roles.get(role)?.props['aria-busy'] === undefined) {
44
+ throw new Error(`"aria-busy" is not supported on role "${role}".`);
45
+ }
46
+ }
47
+ if (checked !== undefined) {
48
+ // guard against unknown roles
49
+ if (_ariaQuery.roles.get(role)?.props['aria-checked'] === undefined) {
50
+ throw new Error(`"aria-checked" is not supported on role "${role}".`);
51
+ }
52
+ }
53
+ if (pressed !== undefined) {
54
+ // guard against unknown roles
55
+ if (_ariaQuery.roles.get(role)?.props['aria-pressed'] === undefined) {
56
+ throw new Error(`"aria-pressed" is not supported on role "${role}".`);
57
+ }
58
+ }
59
+ if (current !== undefined) {
60
+ /* istanbul ignore next */
61
+ // guard against unknown roles
62
+ // All currently released ARIA versions support `aria-current` on all roles.
63
+ // Leaving this for symmetry and forward compatibility
64
+ if (_ariaQuery.roles.get(role)?.props['aria-current'] === undefined) {
65
+ throw new Error(`"aria-current" is not supported on role "${role}".`);
66
+ }
67
+ }
68
+ if (level !== undefined) {
69
+ // guard against using `level` option with any role other than `heading`
70
+ if (role !== 'heading') {
71
+ throw new Error(`Role "${role}" cannot have "level" property.`);
72
+ }
73
+ }
74
+ if (valueNow !== undefined) {
75
+ // guard against unknown roles
76
+ if (_ariaQuery.roles.get(role)?.props['aria-valuenow'] === undefined) {
77
+ throw new Error(`"aria-valuenow" is not supported on role "${role}".`);
78
+ }
79
+ }
80
+ if (valueMax !== undefined) {
81
+ // guard against unknown roles
82
+ if (_ariaQuery.roles.get(role)?.props['aria-valuemax'] === undefined) {
83
+ throw new Error(`"aria-valuemax" is not supported on role "${role}".`);
84
+ }
85
+ }
86
+ if (valueMin !== undefined) {
87
+ // guard against unknown roles
88
+ if (_ariaQuery.roles.get(role)?.props['aria-valuemin'] === undefined) {
89
+ throw new Error(`"aria-valuemin" is not supported on role "${role}".`);
90
+ }
91
+ }
92
+ if (valueText !== undefined) {
93
+ // guard against unknown roles
94
+ if (_ariaQuery.roles.get(role)?.props['aria-valuetext'] === undefined) {
95
+ throw new Error(`"aria-valuetext" is not supported on role "${role}".`);
96
+ }
97
+ }
98
+ if (expanded !== undefined) {
99
+ // guard against unknown roles
100
+ if (_ariaQuery.roles.get(role)?.props['aria-expanded'] === undefined) {
101
+ throw new Error(`"aria-expanded" is not supported on role "${role}".`);
102
+ }
103
+ }
104
+ const subtreeIsInaccessibleCache = new WeakMap();
105
+ function cachedIsSubtreeInaccessible(element) {
106
+ if (!subtreeIsInaccessibleCache.has(element)) {
107
+ subtreeIsInaccessibleCache.set(element, (0, _roleHelpers.isSubtreeInaccessible)(element));
108
+ }
109
+ return subtreeIsInaccessibleCache.get(element);
110
+ }
111
+ return Array.from(container.querySelectorAll(
112
+ // Only query elements that can be matched by the following filters
113
+ makeRoleSelector(role))).filter(node => {
114
+ const isRoleSpecifiedExplicitly = node.hasAttribute('role');
115
+ if (isRoleSpecifiedExplicitly) {
116
+ const roleValue = node.getAttribute('role');
117
+ if (queryFallbacks) {
118
+ return roleValue.split(' ').filter(Boolean).some(roleAttributeToken => roleAttributeToken === role);
119
+ }
120
+ // other wise only send the first token to match
121
+ const [firstRoleAttributeToken] = roleValue.split(' ');
122
+ return firstRoleAttributeToken === role;
123
+ }
124
+ const implicitRoles = (0, _roleHelpers.getImplicitAriaRoles)(node);
125
+ return implicitRoles.some(implicitRole => {
126
+ return implicitRole === role;
127
+ });
128
+ }).filter(element => {
129
+ if (selected !== undefined) {
130
+ return selected === (0, _roleHelpers.computeAriaSelected)(element);
131
+ }
132
+ if (busy !== undefined) {
133
+ return busy === (0, _roleHelpers.computeAriaBusy)(element);
134
+ }
135
+ if (checked !== undefined) {
136
+ return checked === (0, _roleHelpers.computeAriaChecked)(element);
137
+ }
138
+ if (pressed !== undefined) {
139
+ return pressed === (0, _roleHelpers.computeAriaPressed)(element);
140
+ }
141
+ if (current !== undefined) {
142
+ return current === (0, _roleHelpers.computeAriaCurrent)(element);
143
+ }
144
+ if (expanded !== undefined) {
145
+ return expanded === (0, _roleHelpers.computeAriaExpanded)(element);
146
+ }
147
+ if (level !== undefined) {
148
+ return level === (0, _roleHelpers.computeHeadingLevel)(element);
149
+ }
150
+ if (valueNow !== undefined || valueMax !== undefined || valueMin !== undefined || valueText !== undefined) {
151
+ let valueMatches = true;
152
+ if (valueNow !== undefined) {
153
+ valueMatches &&= valueNow === (0, _roleHelpers.computeAriaValueNow)(element);
154
+ }
155
+ if (valueMax !== undefined) {
156
+ valueMatches &&= valueMax === (0, _roleHelpers.computeAriaValueMax)(element);
157
+ }
158
+ if (valueMin !== undefined) {
159
+ valueMatches &&= valueMin === (0, _roleHelpers.computeAriaValueMin)(element);
160
+ }
161
+ if (valueText !== undefined) {
162
+ valueMatches &&= (0, _allUtils.matches)((0, _roleHelpers.computeAriaValueText)(element) ?? null, element, valueText, text => text);
163
+ }
164
+ return valueMatches;
165
+ }
166
+ // don't care if aria attributes are unspecified
167
+ return true;
168
+ }).filter(element => {
169
+ if (name === undefined) {
170
+ // Don't care
171
+ return true;
172
+ }
173
+ return (0, _allUtils.matches)((0, _domAccessibilityApi.computeAccessibleName)(element, {
174
+ computedStyleSupportsPseudoElements: (0, _allUtils.getConfig)().computedStyleSupportsPseudoElements
175
+ }), element, name, text => text);
176
+ }).filter(element => {
177
+ if (description === undefined) {
178
+ // Don't care
179
+ return true;
180
+ }
181
+ return (0, _allUtils.matches)((0, _domAccessibilityApi.computeAccessibleDescription)(element, {
182
+ computedStyleSupportsPseudoElements: (0, _allUtils.getConfig)().computedStyleSupportsPseudoElements
183
+ }), element, description, text => text);
184
+ }).filter(element => {
185
+ return hidden === false ? (0, _roleHelpers.isInaccessible)(element, {
186
+ isSubtreeInaccessible: cachedIsSubtreeInaccessible
187
+ }) === false : true;
188
+ });
189
+ };
190
+ function makeRoleSelector(role) {
191
+ const explicitRoleSelector = `*[role~="${role}"]`;
192
+ const roleRelations = _ariaQuery.roleElements.get(role) ?? new Set();
193
+ const implicitRoleSelectors = new Set(Array.from(roleRelations).map(({
194
+ name
195
+ }) => name));
196
+
197
+ // Current transpilation config sometimes assumes `...` is always applied to arrays.
198
+ // `...` is equivalent to `Array.prototype.concat` for arrays.
199
+ // If you replace this code with `[explicitRoleSelector, ...implicitRoleSelectors]`, make sure every transpilation target retains the `...` in favor of `Array.prototype.concat`.
200
+ return [explicitRoleSelector].concat(Array.from(implicitRoleSelectors)).join(',');
201
+ }
202
+ const getNameHint = name => {
203
+ let nameHint = '';
204
+ if (name === undefined) {
205
+ nameHint = '';
206
+ } else if (typeof name === 'string') {
207
+ nameHint = ` and name "${name}"`;
208
+ } else {
209
+ nameHint = ` and name \`${name}\``;
210
+ }
211
+ return nameHint;
212
+ };
213
+ const getMultipleError = (c, role, {
214
+ name
215
+ } = {}) => {
216
+ return `Found multiple elements with the role "${role}"${getNameHint(name)}`;
217
+ };
218
+ const getMissingError = (container, role, {
219
+ hidden = (0, _allUtils.getConfig)().defaultHidden,
220
+ name,
221
+ description
222
+ } = {}) => {
223
+ if ((0, _allUtils.getConfig)()._disableExpensiveErrorDiagnostics) {
224
+ return `Unable to find role="${role}"${getNameHint(name)}`;
225
+ }
226
+ let roles = '';
227
+ Array.from(container.children).forEach(childElement => {
228
+ roles += (0, _roleHelpers.prettyRoles)(childElement, {
229
+ hidden,
230
+ includeDescription: description !== undefined
231
+ });
232
+ });
233
+ let roleMessage;
234
+ if (roles.length === 0) {
235
+ if (hidden === false) {
236
+ roleMessage = 'There are no accessible roles. But there might be some inaccessible roles. ' + 'If you wish to access them, then set the `hidden` option to `true`. ' + 'Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole';
237
+ } else {
238
+ roleMessage = 'There are no available roles.';
239
+ }
240
+ } else {
241
+ roleMessage = `
242
+ Here are the ${hidden === false ? 'accessible' : 'available'} roles:
243
+
244
+ ${roles.replace(/\n/g, '\n ').replace(/\n\s\s\n/g, '\n\n')}
245
+ `.trim();
246
+ }
247
+ let nameHint = '';
248
+ if (name === undefined) {
249
+ nameHint = '';
250
+ } else if (typeof name === 'string') {
251
+ nameHint = ` and name "${name}"`;
252
+ } else {
253
+ nameHint = ` and name \`${name}\``;
254
+ }
255
+ let descriptionHint = '';
256
+ if (description === undefined) {
257
+ descriptionHint = '';
258
+ } else if (typeof description === 'string') {
259
+ descriptionHint = ` and description "${description}"`;
260
+ } else {
261
+ descriptionHint = ` and description \`${description}\``;
262
+ }
263
+ return `
264
+ Unable to find an ${hidden === false ? 'accessible ' : ''}element with the role "${role}"${nameHint}${descriptionHint}
265
+
266
+ ${roleMessage}`.trim();
267
+ };
268
+ const queryAllByRoleWithSuggestions = exports.queryAllByRole = (0, _queryHelpers.wrapAllByQueryWithSuggestion)(queryAllByRole, queryAllByRole.name, 'queryAll');
269
+ const [queryByRole, getAllByRole, getByRole, findAllByRole, findByRole] = (0, _allUtils.buildQueries)(queryAllByRole, getMultipleError, getMissingError);
270
+ exports.findByRole = findByRole;
271
+ exports.findAllByRole = findAllByRole;
272
+ exports.getByRole = getByRole;
273
+ exports.getAllByRole = getAllByRole;
274
+ exports.queryByRole = queryByRole;
node_modules/@testing-library/dom/dist/queries/test-id.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.queryByTestId = exports.queryAllByTestId = exports.getByTestId = exports.getAllByTestId = exports.findByTestId = exports.findAllByTestId = void 0;
7
+ var _helpers = require("../helpers");
8
+ var _queryHelpers = require("../query-helpers");
9
+ var _allUtils = require("./all-utils");
10
+ const getTestIdAttribute = () => (0, _allUtils.getConfig)().testIdAttribute;
11
+ const queryAllByTestId = (...args) => {
12
+ (0, _helpers.checkContainerType)(args[0]);
13
+ return (0, _allUtils.queryAllByAttribute)(getTestIdAttribute(), ...args);
14
+ };
15
+ const getMultipleError = (c, id) => `Found multiple elements by: [${getTestIdAttribute()}="${id}"]`;
16
+ const getMissingError = (c, id) => `Unable to find an element by: [${getTestIdAttribute()}="${id}"]`;
17
+ const queryAllByTestIdWithSuggestions = exports.queryAllByTestId = (0, _queryHelpers.wrapAllByQueryWithSuggestion)(queryAllByTestId, queryAllByTestId.name, 'queryAll');
18
+ const [queryByTestId, getAllByTestId, getByTestId, findAllByTestId, findByTestId] = (0, _allUtils.buildQueries)(queryAllByTestId, getMultipleError, getMissingError);
19
+ exports.findByTestId = findByTestId;
20
+ exports.findAllByTestId = findAllByTestId;
21
+ exports.getByTestId = getByTestId;
22
+ exports.getAllByTestId = getAllByTestId;
23
+ exports.queryByTestId = queryByTestId;
node_modules/@testing-library/dom/dist/queries/text.js ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.queryByText = exports.queryAllByText = exports.getByText = exports.getAllByText = exports.findByText = exports.findAllByText = void 0;
7
+ var _queryHelpers = require("../query-helpers");
8
+ var _helpers = require("../helpers");
9
+ var _allUtils = require("./all-utils");
10
+ const queryAllByText = (container, text, {
11
+ selector = '*',
12
+ exact = true,
13
+ collapseWhitespace,
14
+ trim,
15
+ ignore = (0, _allUtils.getConfig)().defaultIgnore,
16
+ normalizer
17
+ } = {}) => {
18
+ (0, _helpers.checkContainerType)(container);
19
+ const matcher = exact ? _allUtils.matches : _allUtils.fuzzyMatches;
20
+ const matchNormalizer = (0, _allUtils.makeNormalizer)({
21
+ collapseWhitespace,
22
+ trim,
23
+ normalizer
24
+ });
25
+ let baseArray = [];
26
+ if (typeof container.matches === 'function' && container.matches(selector)) {
27
+ baseArray = [container];
28
+ }
29
+ return [...baseArray, ...Array.from(container.querySelectorAll(selector))]
30
+ // TODO: `matches` according lib.dom.d.ts can get only `string` but according our code it can handle also boolean :)
31
+ .filter(node => !ignore || !node.matches(ignore)).filter(node => matcher((0, _allUtils.getNodeText)(node), node, text, matchNormalizer));
32
+ };
33
+ const getMultipleError = (c, text) => `Found multiple elements with the text: ${text}`;
34
+ const getMissingError = (c, text, options = {}) => {
35
+ const {
36
+ collapseWhitespace,
37
+ trim,
38
+ normalizer,
39
+ selector
40
+ } = options;
41
+ const matchNormalizer = (0, _allUtils.makeNormalizer)({
42
+ collapseWhitespace,
43
+ trim,
44
+ normalizer
45
+ });
46
+ const normalizedText = matchNormalizer(text.toString());
47
+ const isNormalizedDifferent = normalizedText !== text.toString();
48
+ const isCustomSelector = (selector ?? '*') !== '*';
49
+ return `Unable to find an element with the text: ${isNormalizedDifferent ? `${normalizedText} (normalized from '${text}')` : text}${isCustomSelector ? `, which matches selector '${selector}'` : ''}. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.`;
50
+ };
51
+ const queryAllByTextWithSuggestions = exports.queryAllByText = (0, _queryHelpers.wrapAllByQueryWithSuggestion)(queryAllByText, queryAllByText.name, 'queryAll');
52
+ const [queryByText, getAllByText, getByText, findAllByText, findByText] = (0, _allUtils.buildQueries)(queryAllByText, getMultipleError, getMissingError);
53
+ exports.findByText = findByText;
54
+ exports.findAllByText = findAllByText;
55
+ exports.getByText = getByText;
56
+ exports.getAllByText = getAllByText;
57
+ exports.queryByText = queryByText;
node_modules/@testing-library/dom/dist/queries/title.js ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.queryByTitle = exports.queryAllByTitle = exports.getByTitle = exports.getAllByTitle = exports.findByTitle = exports.findAllByTitle = void 0;
7
+ var _queryHelpers = require("../query-helpers");
8
+ var _helpers = require("../helpers");
9
+ var _allUtils = require("./all-utils");
10
+ const isSvgTitle = node => node.tagName.toLowerCase() === 'title' && node.parentElement?.tagName.toLowerCase() === 'svg';
11
+ const queryAllByTitle = (container, text, {
12
+ exact = true,
13
+ collapseWhitespace,
14
+ trim,
15
+ normalizer
16
+ } = {}) => {
17
+ (0, _helpers.checkContainerType)(container);
18
+ const matcher = exact ? _allUtils.matches : _allUtils.fuzzyMatches;
19
+ const matchNormalizer = (0, _allUtils.makeNormalizer)({
20
+ collapseWhitespace,
21
+ trim,
22
+ normalizer
23
+ });
24
+ return Array.from(container.querySelectorAll('[title], svg > title')).filter(node => matcher(node.getAttribute('title'), node, text, matchNormalizer) || isSvgTitle(node) && matcher((0, _allUtils.getNodeText)(node), node, text, matchNormalizer));
25
+ };
26
+ const getMultipleError = (c, title) => `Found multiple elements with the title: ${title}.`;
27
+ const getMissingError = (c, title) => `Unable to find an element with the title: ${title}.`;
28
+ const queryAllByTitleWithSuggestions = exports.queryAllByTitle = (0, _queryHelpers.wrapAllByQueryWithSuggestion)(queryAllByTitle, queryAllByTitle.name, 'queryAll');
29
+ const [queryByTitle, getAllByTitle, getByTitle, findAllByTitle, findByTitle] = (0, _allUtils.buildQueries)(queryAllByTitle, getMultipleError, getMissingError);
30
+ exports.findByTitle = findByTitle;
31
+ exports.findAllByTitle = findAllByTitle;
32
+ exports.getByTitle = getByTitle;
33
+ exports.getAllByTitle = getAllByTitle;
34
+ exports.queryByTitle = queryByTitle;
node_modules/@testing-library/dom/dist/query-helpers.js ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.buildQueries = buildQueries;
7
+ exports.getElementError = getElementError;
8
+ exports.getMultipleElementsFoundError = getMultipleElementsFoundError;
9
+ exports.makeFindQuery = makeFindQuery;
10
+ exports.makeGetAllQuery = makeGetAllQuery;
11
+ exports.makeSingleQuery = makeSingleQuery;
12
+ exports.queryAllByAttribute = queryAllByAttribute;
13
+ exports.queryByAttribute = queryByAttribute;
14
+ exports.wrapSingleQueryWithSuggestion = exports.wrapAllByQueryWithSuggestion = void 0;
15
+ var _suggestions = require("./suggestions");
16
+ var _matches = require("./matches");
17
+ var _waitFor = require("./wait-for");
18
+ var _config = require("./config");
19
+ function getElementError(message, container) {
20
+ return (0, _config.getConfig)().getElementError(message, container);
21
+ }
22
+ function getMultipleElementsFoundError(message, container) {
23
+ return getElementError(`${message}\n\n(If this is intentional, then use the \`*AllBy*\` variant of the query (like \`queryAllByText\`, \`getAllByText\`, or \`findAllByText\`)).`, container);
24
+ }
25
+ function queryAllByAttribute(attribute, container, text, {
26
+ exact = true,
27
+ collapseWhitespace,
28
+ trim,
29
+ normalizer
30
+ } = {}) {
31
+ const matcher = exact ? _matches.matches : _matches.fuzzyMatches;
32
+ const matchNormalizer = (0, _matches.makeNormalizer)({
33
+ collapseWhitespace,
34
+ trim,
35
+ normalizer
36
+ });
37
+ return Array.from(container.querySelectorAll(`[${attribute}]`)).filter(node => matcher(node.getAttribute(attribute), node, text, matchNormalizer));
38
+ }
39
+ function queryByAttribute(attribute, container, text, options) {
40
+ const els = queryAllByAttribute(attribute, container, text, options);
41
+ if (els.length > 1) {
42
+ throw getMultipleElementsFoundError(`Found multiple elements by [${attribute}=${text}]`, container);
43
+ }
44
+ return els[0] || null;
45
+ }
46
+
47
+ // this accepts a query function and returns a function which throws an error
48
+ // if more than one elements is returned, otherwise it returns the first
49
+ // element or null
50
+ function makeSingleQuery(allQuery, getMultipleError) {
51
+ return (container, ...args) => {
52
+ const els = allQuery(container, ...args);
53
+ if (els.length > 1) {
54
+ const elementStrings = els.map(element => getElementError(null, element).message).join('\n\n');
55
+ throw getMultipleElementsFoundError(`${getMultipleError(container, ...args)}
56
+
57
+ Here are the matching elements:
58
+
59
+ ${elementStrings}`, container);
60
+ }
61
+ return els[0] || null;
62
+ };
63
+ }
64
+ function getSuggestionError(suggestion, container) {
65
+ return (0, _config.getConfig)().getElementError(`A better query is available, try this:
66
+ ${suggestion.toString()}
67
+ `, container);
68
+ }
69
+
70
+ // this accepts a query function and returns a function which throws an error
71
+ // if an empty list of elements is returned
72
+ function makeGetAllQuery(allQuery, getMissingError) {
73
+ return (container, ...args) => {
74
+ const els = allQuery(container, ...args);
75
+ if (!els.length) {
76
+ throw (0, _config.getConfig)().getElementError(getMissingError(container, ...args), container);
77
+ }
78
+ return els;
79
+ };
80
+ }
81
+
82
+ // this accepts a getter query function and returns a function which calls
83
+ // waitFor and passing a function which invokes the getter.
84
+ function makeFindQuery(getter) {
85
+ return (container, text, options, waitForOptions) => {
86
+ return (0, _waitFor.waitFor)(() => {
87
+ return getter(container, text, options);
88
+ }, {
89
+ container,
90
+ ...waitForOptions
91
+ });
92
+ };
93
+ }
94
+ const wrapSingleQueryWithSuggestion = (query, queryAllByName, variant) => (container, ...args) => {
95
+ const element = query(container, ...args);
96
+ const [{
97
+ suggest = (0, _config.getConfig)().throwSuggestions
98
+ } = {}] = args.slice(-1);
99
+ if (element && suggest) {
100
+ const suggestion = (0, _suggestions.getSuggestedQuery)(element, variant);
101
+ if (suggestion && !queryAllByName.endsWith(suggestion.queryName)) {
102
+ throw getSuggestionError(suggestion.toString(), container);
103
+ }
104
+ }
105
+ return element;
106
+ };
107
+ exports.wrapSingleQueryWithSuggestion = wrapSingleQueryWithSuggestion;
108
+ const wrapAllByQueryWithSuggestion = (query, queryAllByName, variant) => (container, ...args) => {
109
+ const els = query(container, ...args);
110
+ const [{
111
+ suggest = (0, _config.getConfig)().throwSuggestions
112
+ } = {}] = args.slice(-1);
113
+ if (els.length && suggest) {
114
+ // get a unique list of all suggestion messages. We are only going to make a suggestion if
115
+ // all the suggestions are the same
116
+ const uniqueSuggestionMessages = [...new Set(els.map(element => (0, _suggestions.getSuggestedQuery)(element, variant)?.toString()))];
117
+ if (
118
+ // only want to suggest if all the els have the same suggestion.
119
+ uniqueSuggestionMessages.length === 1 && !queryAllByName.endsWith(
120
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- TODO: Can this be null at runtime?
121
+ (0, _suggestions.getSuggestedQuery)(els[0], variant).queryName)) {
122
+ throw getSuggestionError(uniqueSuggestionMessages[0], container);
123
+ }
124
+ }
125
+ return els;
126
+ };
127
+
128
+ // TODO: This deviates from the published declarations
129
+ // However, the implementation always required a dyadic (after `container`) not variadic `queryAllBy` considering the implementation of `makeFindQuery`
130
+ // This is at least statically true and can be verified by accepting `QueryMethod<Arguments, HTMLElement[]>`
131
+ exports.wrapAllByQueryWithSuggestion = wrapAllByQueryWithSuggestion;
132
+ function buildQueries(queryAllBy, getMultipleError, getMissingError) {
133
+ const queryBy = wrapSingleQueryWithSuggestion(makeSingleQuery(queryAllBy, getMultipleError), queryAllBy.name, 'query');
134
+ const getAllBy = makeGetAllQuery(queryAllBy, getMissingError);
135
+ const getBy = makeSingleQuery(getAllBy, getMultipleError);
136
+ const getByWithSuggestions = wrapSingleQueryWithSuggestion(getBy, queryAllBy.name, 'get');
137
+ const getAllWithSuggestions = wrapAllByQueryWithSuggestion(getAllBy, queryAllBy.name.replace('query', 'get'), 'getAll');
138
+ const findAllBy = makeFindQuery(wrapAllByQueryWithSuggestion(getAllBy, queryAllBy.name, 'findAll'));
139
+ const findBy = makeFindQuery(wrapSingleQueryWithSuggestion(getBy, queryAllBy.name, 'find'));
140
+ return [queryBy, getAllWithSuggestions, getByWithSuggestions, findAllBy, findBy];
141
+ }
node_modules/@testing-library/dom/dist/role-helpers.js ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.computeAriaBusy = computeAriaBusy;
7
+ exports.computeAriaChecked = computeAriaChecked;
8
+ exports.computeAriaCurrent = computeAriaCurrent;
9
+ exports.computeAriaExpanded = computeAriaExpanded;
10
+ exports.computeAriaPressed = computeAriaPressed;
11
+ exports.computeAriaSelected = computeAriaSelected;
12
+ exports.computeAriaValueMax = computeAriaValueMax;
13
+ exports.computeAriaValueMin = computeAriaValueMin;
14
+ exports.computeAriaValueNow = computeAriaValueNow;
15
+ exports.computeAriaValueText = computeAriaValueText;
16
+ exports.computeHeadingLevel = computeHeadingLevel;
17
+ exports.getImplicitAriaRoles = getImplicitAriaRoles;
18
+ exports.getRoles = getRoles;
19
+ exports.isInaccessible = isInaccessible;
20
+ exports.isSubtreeInaccessible = isSubtreeInaccessible;
21
+ exports.logRoles = void 0;
22
+ exports.prettyRoles = prettyRoles;
23
+ var _ariaQuery = require("aria-query");
24
+ var _domAccessibilityApi = require("dom-accessibility-api");
25
+ var _prettyDom = require("./pretty-dom");
26
+ var _config = require("./config");
27
+ const elementRoleList = buildElementRoleList(_ariaQuery.elementRoles);
28
+
29
+ /**
30
+ * @param {Element} element -
31
+ * @returns {boolean} - `true` if `element` and its subtree are inaccessible
32
+ */
33
+ function isSubtreeInaccessible(element) {
34
+ if (element.hidden === true) {
35
+ return true;
36
+ }
37
+ if (element.getAttribute('aria-hidden') === 'true') {
38
+ return true;
39
+ }
40
+ const window = element.ownerDocument.defaultView;
41
+ if (window.getComputedStyle(element).display === 'none') {
42
+ return true;
43
+ }
44
+ return false;
45
+ }
46
+
47
+ /**
48
+ * Partial implementation https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
49
+ * which should only be used for elements with a non-presentational role i.e.
50
+ * `role="none"` and `role="presentation"` will not be excluded.
51
+ *
52
+ * Implements aria-hidden semantics (i.e. parent overrides child)
53
+ * Ignores "Child Presentational: True" characteristics
54
+ *
55
+ * @param {Element} element -
56
+ * @param {object} [options] -
57
+ * @param {function (element: Element): boolean} options.isSubtreeInaccessible -
58
+ * can be used to return cached results from previous isSubtreeInaccessible calls
59
+ * @returns {boolean} true if excluded, otherwise false
60
+ */
61
+ function isInaccessible(element, options = {}) {
62
+ const {
63
+ isSubtreeInaccessible: isSubtreeInaccessibleImpl = isSubtreeInaccessible
64
+ } = options;
65
+ const window = element.ownerDocument.defaultView;
66
+ // since visibility is inherited we can exit early
67
+ if (window.getComputedStyle(element).visibility === 'hidden') {
68
+ return true;
69
+ }
70
+ let currentElement = element;
71
+ while (currentElement) {
72
+ if (isSubtreeInaccessibleImpl(currentElement)) {
73
+ return true;
74
+ }
75
+ currentElement = currentElement.parentElement;
76
+ }
77
+ return false;
78
+ }
79
+ function getImplicitAriaRoles(currentNode) {
80
+ // eslint bug here:
81
+ // eslint-disable-next-line no-unused-vars
82
+ for (const {
83
+ match,
84
+ roles
85
+ } of elementRoleList) {
86
+ if (match(currentNode)) {
87
+ return [...roles];
88
+ }
89
+ }
90
+ return [];
91
+ }
92
+ function buildElementRoleList(elementRolesMap) {
93
+ function makeElementSelector({
94
+ name,
95
+ attributes
96
+ }) {
97
+ return `${name}${attributes.map(({
98
+ name: attributeName,
99
+ value,
100
+ constraints = []
101
+ }) => {
102
+ const shouldNotExist = constraints.indexOf('undefined') !== -1;
103
+ const shouldBeNonEmpty = constraints.indexOf('set') !== -1;
104
+ const hasExplicitValue = typeof value !== 'undefined';
105
+ if (hasExplicitValue) {
106
+ return `[${attributeName}="${value}"]`;
107
+ } else if (shouldNotExist) {
108
+ return `:not([${attributeName}])`;
109
+ } else if (shouldBeNonEmpty) {
110
+ return `[${attributeName}]:not([${attributeName}=""])`;
111
+ }
112
+ return `[${attributeName}]`;
113
+ }).join('')}`;
114
+ }
115
+ function getSelectorSpecificity({
116
+ attributes = []
117
+ }) {
118
+ return attributes.length;
119
+ }
120
+ function bySelectorSpecificity({
121
+ specificity: leftSpecificity
122
+ }, {
123
+ specificity: rightSpecificity
124
+ }) {
125
+ return rightSpecificity - leftSpecificity;
126
+ }
127
+ function match(element) {
128
+ let {
129
+ attributes = []
130
+ } = element;
131
+
132
+ // https://github.com/testing-library/dom-testing-library/issues/814
133
+ const typeTextIndex = attributes.findIndex(attribute => attribute.value && attribute.name === 'type' && attribute.value === 'text');
134
+ if (typeTextIndex >= 0) {
135
+ // not using splice to not mutate the attributes array
136
+ attributes = [...attributes.slice(0, typeTextIndex), ...attributes.slice(typeTextIndex + 1)];
137
+ }
138
+ const selector = makeElementSelector({
139
+ ...element,
140
+ attributes
141
+ });
142
+ return node => {
143
+ if (typeTextIndex >= 0 && node.type !== 'text') {
144
+ return false;
145
+ }
146
+ return node.matches(selector);
147
+ };
148
+ }
149
+ let result = [];
150
+
151
+ // eslint bug here:
152
+ // eslint-disable-next-line no-unused-vars
153
+ for (const [element, roles] of elementRolesMap.entries()) {
154
+ result = [...result, {
155
+ match: match(element),
156
+ roles: Array.from(roles),
157
+ specificity: getSelectorSpecificity(element)
158
+ }];
159
+ }
160
+ return result.sort(bySelectorSpecificity);
161
+ }
162
+ function getRoles(container, {
163
+ hidden = false
164
+ } = {}) {
165
+ function flattenDOM(node) {
166
+ return [node, ...Array.from(node.children).reduce((acc, child) => [...acc, ...flattenDOM(child)], [])];
167
+ }
168
+ return flattenDOM(container).filter(element => {
169
+ return hidden === false ? isInaccessible(element) === false : true;
170
+ }).reduce((acc, node) => {
171
+ let roles = [];
172
+ // TODO: This violates html-aria which does not allow any role on every element
173
+ if (node.hasAttribute('role')) {
174
+ roles = node.getAttribute('role').split(' ').slice(0, 1);
175
+ } else {
176
+ roles = getImplicitAriaRoles(node);
177
+ }
178
+ return roles.reduce((rolesAcc, role) => Array.isArray(rolesAcc[role]) ? {
179
+ ...rolesAcc,
180
+ [role]: [...rolesAcc[role], node]
181
+ } : {
182
+ ...rolesAcc,
183
+ [role]: [node]
184
+ }, acc);
185
+ }, {});
186
+ }
187
+ function prettyRoles(dom, {
188
+ hidden,
189
+ includeDescription
190
+ }) {
191
+ const roles = getRoles(dom, {
192
+ hidden
193
+ });
194
+ // We prefer to skip generic role, we don't recommend it
195
+ return Object.entries(roles).filter(([role]) => role !== 'generic').map(([role, elements]) => {
196
+ const delimiterBar = '-'.repeat(50);
197
+ const elementsString = elements.map(el => {
198
+ const nameString = `Name "${(0, _domAccessibilityApi.computeAccessibleName)(el, {
199
+ computedStyleSupportsPseudoElements: (0, _config.getConfig)().computedStyleSupportsPseudoElements
200
+ })}":\n`;
201
+ const domString = (0, _prettyDom.prettyDOM)(el.cloneNode(false));
202
+ if (includeDescription) {
203
+ const descriptionString = `Description "${(0, _domAccessibilityApi.computeAccessibleDescription)(el, {
204
+ computedStyleSupportsPseudoElements: (0, _config.getConfig)().computedStyleSupportsPseudoElements
205
+ })}":\n`;
206
+ return `${nameString}${descriptionString}${domString}`;
207
+ }
208
+ return `${nameString}${domString}`;
209
+ }).join('\n\n');
210
+ return `${role}:\n\n${elementsString}\n\n${delimiterBar}`;
211
+ }).join('\n');
212
+ }
213
+ const logRoles = (dom, {
214
+ hidden = false
215
+ } = {}) => console.log(prettyRoles(dom, {
216
+ hidden
217
+ }));
218
+
219
+ /**
220
+ * @param {Element} element -
221
+ * @returns {boolean | undefined} - false/true if (not)selected, undefined if not selectable
222
+ */
223
+ exports.logRoles = logRoles;
224
+ function computeAriaSelected(element) {
225
+ // implicit value from html-aam mappings: https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
226
+ // https://www.w3.org/TR/html-aam-1.0/#details-id-97
227
+ if (element.tagName === 'OPTION') {
228
+ return element.selected;
229
+ }
230
+
231
+ // explicit value
232
+ return checkBooleanAttribute(element, 'aria-selected');
233
+ }
234
+
235
+ /**
236
+ * @param {Element} element -
237
+ * @returns {boolean} -
238
+ */
239
+ function computeAriaBusy(element) {
240
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-busy
241
+ return element.getAttribute('aria-busy') === 'true';
242
+ }
243
+
244
+ /**
245
+ * @param {Element} element -
246
+ * @returns {boolean | undefined} - false/true if (not)checked, undefined if not checked-able
247
+ */
248
+ function computeAriaChecked(element) {
249
+ // implicit value from html-aam mappings: https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
250
+ // https://www.w3.org/TR/html-aam-1.0/#details-id-56
251
+ // https://www.w3.org/TR/html-aam-1.0/#details-id-67
252
+ if ('indeterminate' in element && element.indeterminate) {
253
+ return undefined;
254
+ }
255
+ if ('checked' in element) {
256
+ return element.checked;
257
+ }
258
+
259
+ // explicit value
260
+ return checkBooleanAttribute(element, 'aria-checked');
261
+ }
262
+
263
+ /**
264
+ * @param {Element} element -
265
+ * @returns {boolean | undefined} - false/true if (not)pressed, undefined if not press-able
266
+ */
267
+ function computeAriaPressed(element) {
268
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-pressed
269
+ return checkBooleanAttribute(element, 'aria-pressed');
270
+ }
271
+
272
+ /**
273
+ * @param {Element} element -
274
+ * @returns {boolean | string | null} -
275
+ */
276
+ function computeAriaCurrent(element) {
277
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-current
278
+ return checkBooleanAttribute(element, 'aria-current') ?? element.getAttribute('aria-current') ?? false;
279
+ }
280
+
281
+ /**
282
+ * @param {Element} element -
283
+ * @returns {boolean | undefined} - false/true if (not)expanded, undefined if not expand-able
284
+ */
285
+ function computeAriaExpanded(element) {
286
+ // https://www.w3.org/TR/wai-aria-1.1/#aria-expanded
287
+ return checkBooleanAttribute(element, 'aria-expanded');
288
+ }
289
+ function checkBooleanAttribute(element, attribute) {
290
+ const attributeValue = element.getAttribute(attribute);
291
+ if (attributeValue === 'true') {
292
+ return true;
293
+ }
294
+ if (attributeValue === 'false') {
295
+ return false;
296
+ }
297
+ return undefined;
298
+ }
299
+
300
+ /**
301
+ * @param {Element} element -
302
+ * @returns {number | undefined} - number if implicit heading or aria-level present, otherwise undefined
303
+ */
304
+ function computeHeadingLevel(element) {
305
+ // https://w3c.github.io/html-aam/#el-h1-h6
306
+ // https://w3c.github.io/html-aam/#el-h1-h6
307
+ const implicitHeadingLevels = {
308
+ H1: 1,
309
+ H2: 2,
310
+ H3: 3,
311
+ H4: 4,
312
+ H5: 5,
313
+ H6: 6
314
+ };
315
+ // explicit aria-level value
316
+ // https://www.w3.org/TR/wai-aria-1.2/#aria-level
317
+ const ariaLevelAttribute = element.getAttribute('aria-level') && Number(element.getAttribute('aria-level'));
318
+ return ariaLevelAttribute || implicitHeadingLevels[element.tagName];
319
+ }
320
+
321
+ /**
322
+ * @param {Element} element -
323
+ * @returns {number | undefined} -
324
+ */
325
+ function computeAriaValueNow(element) {
326
+ const valueNow = element.getAttribute('aria-valuenow');
327
+ return valueNow === null ? undefined : +valueNow;
328
+ }
329
+
330
+ /**
331
+ * @param {Element} element -
332
+ * @returns {number | undefined} -
333
+ */
334
+ function computeAriaValueMax(element) {
335
+ const valueMax = element.getAttribute('aria-valuemax');
336
+ return valueMax === null ? undefined : +valueMax;
337
+ }
338
+
339
+ /**
340
+ * @param {Element} element -
341
+ * @returns {number | undefined} -
342
+ */
343
+ function computeAriaValueMin(element) {
344
+ const valueMin = element.getAttribute('aria-valuemin');
345
+ return valueMin === null ? undefined : +valueMin;
346
+ }
347
+
348
+ /**
349
+ * @param {Element} element -
350
+ * @returns {string | undefined} -
351
+ */
352
+ function computeAriaValueText(element) {
353
+ const valueText = element.getAttribute('aria-valuetext');
354
+ return valueText === null ? undefined : valueText;
355
+ }
node_modules/@testing-library/dom/dist/screen.js ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.screen = void 0;
8
+ var _lzString = _interopRequireDefault(require("lz-string"));
9
+ var _getQueriesForElement = require("./get-queries-for-element");
10
+ var _helpers = require("./helpers");
11
+ var _prettyDom = require("./pretty-dom");
12
+ var queries = _interopRequireWildcard(require("./queries"));
13
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
14
+ // WARNING: `lz-string` only has a default export but statically we assume named exports are allowed
15
+ // TODO: Statically verify we don't rely on NodeJS implicit named imports.
16
+
17
+ function unindent(string) {
18
+ // remove white spaces first, to save a few bytes.
19
+ // testing-playground will reformat on load any ways.
20
+ return string.replace(/[ \t]*[\n][ \t]*/g, '\n');
21
+ }
22
+ function encode(value) {
23
+ return _lzString.default.compressToEncodedURIComponent(unindent(value));
24
+ }
25
+ function getPlaygroundUrl(markup) {
26
+ return `https://testing-playground.com/#markup=${encode(markup)}`;
27
+ }
28
+ const debug = (element, maxLength, options) => Array.isArray(element) ? element.forEach(el => (0, _prettyDom.logDOM)(el, maxLength, options)) : (0, _prettyDom.logDOM)(element, maxLength, options);
29
+ const logTestingPlaygroundURL = (element = (0, _helpers.getDocument)().body) => {
30
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
31
+ if (!element || !('innerHTML' in element)) {
32
+ console.log(`The element you're providing isn't a valid DOM element.`);
33
+ return;
34
+ }
35
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
36
+ if (!element.innerHTML) {
37
+ console.log(`The provided element doesn't have any children.`);
38
+ return;
39
+ }
40
+ const playgroundUrl = getPlaygroundUrl(element.innerHTML);
41
+ console.log(`Open this URL in your browser\n\n${playgroundUrl}`);
42
+ return playgroundUrl;
43
+ };
44
+ const initialValue = {
45
+ debug,
46
+ logTestingPlaygroundURL
47
+ };
48
+ const screen = exports.screen = typeof document !== 'undefined' && document.body // eslint-disable-line @typescript-eslint/no-unnecessary-condition
49
+ ? (0, _getQueriesForElement.getQueriesForElement)(document.body, queries, initialValue) : Object.keys(queries).reduce((helpers, key) => {
50
+ // `key` is for all intents and purposes the type of keyof `helpers`, which itself is the type of `initialValue` plus incoming properties from `queries`
51
+ // if `Object.keys(something)` returned Array<keyof typeof something> this explicit type assertion would not be necessary
52
+ // see https://stackoverflow.com/questions/55012174/why-doesnt-object-keys-return-a-keyof-type-in-typescript
53
+ helpers[key] = () => {
54
+ throw new TypeError('For queries bound to document.body a global document has to be available... Learn more: https://testing-library.com/s/screen-global-error');
55
+ };
56
+ return helpers;
57
+ }, initialValue);
node_modules/@testing-library/dom/dist/suggestions.js ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getSuggestedQuery = getSuggestedQuery;
7
+ var _domAccessibilityApi = require("dom-accessibility-api");
8
+ var _matches = require("./matches");
9
+ var _getNodeText = require("./get-node-text");
10
+ var _config = require("./config");
11
+ var _roleHelpers = require("./role-helpers");
12
+ var _labelHelpers = require("./label-helpers");
13
+ const normalize = (0, _matches.getDefaultNormalizer)();
14
+ function escapeRegExp(string) {
15
+ return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
16
+ }
17
+ function getRegExpMatcher(string) {
18
+ return new RegExp(escapeRegExp(string.toLowerCase()), 'i');
19
+ }
20
+ function makeSuggestion(queryName, element, content, {
21
+ variant,
22
+ name
23
+ }) {
24
+ let warning = '';
25
+ const queryOptions = {};
26
+ const queryArgs = [['Role', 'TestId'].includes(queryName) ? content : getRegExpMatcher(content)];
27
+ if (name) {
28
+ queryOptions.name = getRegExpMatcher(name);
29
+ }
30
+ if (queryName === 'Role' && (0, _roleHelpers.isInaccessible)(element)) {
31
+ queryOptions.hidden = true;
32
+ warning = `Element is inaccessible. This means that the element and all its children are invisible to screen readers.
33
+ If you are using the aria-hidden prop, make sure this is the right choice for your case.
34
+ `;
35
+ }
36
+ if (Object.keys(queryOptions).length > 0) {
37
+ queryArgs.push(queryOptions);
38
+ }
39
+ const queryMethod = `${variant}By${queryName}`;
40
+ return {
41
+ queryName,
42
+ queryMethod,
43
+ queryArgs,
44
+ variant,
45
+ warning,
46
+ toString() {
47
+ if (warning) {
48
+ console.warn(warning);
49
+ }
50
+ let [text, options] = queryArgs;
51
+ text = typeof text === 'string' ? `'${text}'` : text;
52
+ options = options ? `, { ${Object.entries(options).map(([k, v]) => `${k}: ${v}`).join(', ')} }` : '';
53
+ return `${queryMethod}(${text}${options})`;
54
+ }
55
+ };
56
+ }
57
+ function canSuggest(currentMethod, requestedMethod, data) {
58
+ return data && (!requestedMethod || requestedMethod.toLowerCase() === currentMethod.toLowerCase());
59
+ }
60
+ function getSuggestedQuery(element, variant = 'get', method) {
61
+ // don't create suggestions for script and style elements
62
+ if (element.matches((0, _config.getConfig)().defaultIgnore)) {
63
+ return undefined;
64
+ }
65
+
66
+ //We prefer to suggest something else if the role is generic
67
+ const role = element.getAttribute('role') ?? (0, _roleHelpers.getImplicitAriaRoles)(element)?.[0];
68
+ if (role !== 'generic' && canSuggest('Role', method, role)) {
69
+ return makeSuggestion('Role', element, role, {
70
+ variant,
71
+ name: (0, _domAccessibilityApi.computeAccessibleName)(element, {
72
+ computedStyleSupportsPseudoElements: (0, _config.getConfig)().computedStyleSupportsPseudoElements
73
+ })
74
+ });
75
+ }
76
+ const labelText = (0, _labelHelpers.getLabels)(document, element).map(label => label.content).join(' ');
77
+ if (canSuggest('LabelText', method, labelText)) {
78
+ return makeSuggestion('LabelText', element, labelText, {
79
+ variant
80
+ });
81
+ }
82
+ const placeholderText = element.getAttribute('placeholder');
83
+ if (canSuggest('PlaceholderText', method, placeholderText)) {
84
+ return makeSuggestion('PlaceholderText', element, placeholderText, {
85
+ variant
86
+ });
87
+ }
88
+ const textContent = normalize((0, _getNodeText.getNodeText)(element));
89
+ if (canSuggest('Text', method, textContent)) {
90
+ return makeSuggestion('Text', element, textContent, {
91
+ variant
92
+ });
93
+ }
94
+ if (canSuggest('DisplayValue', method, element.value)) {
95
+ return makeSuggestion('DisplayValue', element, normalize(element.value), {
96
+ variant
97
+ });
98
+ }
99
+ const alt = element.getAttribute('alt');
100
+ if (canSuggest('AltText', method, alt)) {
101
+ return makeSuggestion('AltText', element, alt, {
102
+ variant
103
+ });
104
+ }
105
+ const title = element.getAttribute('title');
106
+ if (canSuggest('Title', method, title)) {
107
+ return makeSuggestion('Title', element, title, {
108
+ variant
109
+ });
110
+ }
111
+ const testId = element.getAttribute((0, _config.getConfig)().testIdAttribute);
112
+ if (canSuggest('TestId', method, testId)) {
113
+ return makeSuggestion('TestId', element, testId, {
114
+ variant
115
+ });
116
+ }
117
+ return undefined;
118
+ }
node_modules/@testing-library/dom/dist/wait-for-element-to-be-removed.js ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.waitForElementToBeRemoved = waitForElementToBeRemoved;
7
+ var _waitFor = require("./wait-for");
8
+ const isRemoved = result => !result || Array.isArray(result) && !result.length;
9
+
10
+ // Check if the element is not present.
11
+ // As the name implies, waitForElementToBeRemoved should check `present` --> `removed`
12
+ function initialCheck(elements) {
13
+ if (isRemoved(elements)) {
14
+ throw new Error('The element(s) given to waitForElementToBeRemoved are already removed. waitForElementToBeRemoved requires that the element(s) exist(s) before waiting for removal.');
15
+ }
16
+ }
17
+ async function waitForElementToBeRemoved(callback, options) {
18
+ // created here so we get a nice stacktrace
19
+ const timeoutError = new Error('Timed out in waitForElementToBeRemoved.');
20
+ if (typeof callback !== 'function') {
21
+ initialCheck(callback);
22
+ const elements = Array.isArray(callback) ? callback : [callback];
23
+ const getRemainingElements = elements.map(element => {
24
+ let parent = element.parentElement;
25
+ if (parent === null) return () => null;
26
+ while (parent.parentElement) parent = parent.parentElement;
27
+ return () => parent.contains(element) ? element : null;
28
+ });
29
+ callback = () => getRemainingElements.map(c => c()).filter(Boolean);
30
+ }
31
+ initialCheck(callback());
32
+ return (0, _waitFor.waitFor)(() => {
33
+ let result;
34
+ try {
35
+ result = callback();
36
+ } catch (error) {
37
+ if (error.name === 'TestingLibraryElementError') {
38
+ return undefined;
39
+ }
40
+ throw error;
41
+ }
42
+ if (!isRemoved(result)) {
43
+ throw timeoutError;
44
+ }
45
+ return undefined;
46
+ }, options);
47
+ }
48
+
49
+ /*
50
+ eslint
51
+ require-await: "off"
52
+ */
node_modules/@testing-library/dom/dist/wait-for.js ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.waitFor = waitForWrapper;
7
+ var _helpers = require("./helpers");
8
+ var _config = require("./config");
9
+ // This is so the stack trace the developer sees is one that's
10
+ // closer to their code (because async stack traces are hard to follow).
11
+ function copyStackTrace(target, source) {
12
+ target.stack = source.stack.replace(source.message, target.message);
13
+ }
14
+ function waitFor(callback, {
15
+ container = (0, _helpers.getDocument)(),
16
+ timeout = (0, _config.getConfig)().asyncUtilTimeout,
17
+ showOriginalStackTrace = (0, _config.getConfig)().showOriginalStackTrace,
18
+ stackTraceError,
19
+ interval = 50,
20
+ onTimeout = error => {
21
+ Object.defineProperty(error, 'message', {
22
+ value: (0, _config.getConfig)().getElementError(error.message, container).message
23
+ });
24
+ return error;
25
+ },
26
+ mutationObserverOptions = {
27
+ subtree: true,
28
+ childList: true,
29
+ attributes: true,
30
+ characterData: true
31
+ }
32
+ }) {
33
+ if (typeof callback !== 'function') {
34
+ throw new TypeError('Received `callback` arg must be a function');
35
+ }
36
+ return new Promise(async (resolve, reject) => {
37
+ let lastError, intervalId, observer;
38
+ let finished = false;
39
+ let promiseStatus = 'idle';
40
+ const overallTimeoutTimer = setTimeout(handleTimeout, timeout);
41
+ const usingJestFakeTimers = (0, _helpers.jestFakeTimersAreEnabled)();
42
+ if (usingJestFakeTimers) {
43
+ const {
44
+ unstable_advanceTimersWrapper: advanceTimersWrapper
45
+ } = (0, _config.getConfig)();
46
+ checkCallback();
47
+ // this is a dangerous rule to disable because it could lead to an
48
+ // infinite loop. However, eslint isn't smart enough to know that we're
49
+ // setting finished inside `onDone` which will be called when we're done
50
+ // waiting or when we've timed out.
51
+ // eslint-disable-next-line no-unmodified-loop-condition
52
+ while (!finished) {
53
+ if (!(0, _helpers.jestFakeTimersAreEnabled)()) {
54
+ const error = new Error(`Changed from using fake timers to real timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to real timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`);
55
+ if (!showOriginalStackTrace) copyStackTrace(error, stackTraceError);
56
+ reject(error);
57
+ return;
58
+ }
59
+
60
+ // In this rare case, we *need* to wait for in-flight promises
61
+ // to resolve before continuing. We don't need to take advantage
62
+ // of parallelization so we're fine.
63
+ // https://stackoverflow.com/a/59243586/971592
64
+ // eslint-disable-next-line no-await-in-loop
65
+ await advanceTimersWrapper(async () => {
66
+ // we *could* (maybe should?) use `advanceTimersToNextTimer` but it's
67
+ // possible that could make this loop go on forever if someone is using
68
+ // third party code that's setting up recursive timers so rapidly that
69
+ // the user's timer's don't get a chance to resolve. So we'll advance
70
+ // by an interval instead. (We have a test for this case).
71
+ jest.advanceTimersByTime(interval);
72
+ });
73
+
74
+ // Could have timed-out
75
+ if (finished) {
76
+ break;
77
+ }
78
+ // It's really important that checkCallback is run *before* we flush
79
+ // in-flight promises. To be honest, I'm not sure why, and I can't quite
80
+ // think of a way to reproduce the problem in a test, but I spent
81
+ // an entire day banging my head against a wall on this.
82
+ checkCallback();
83
+ }
84
+ } else {
85
+ try {
86
+ (0, _helpers.checkContainerType)(container);
87
+ } catch (e) {
88
+ reject(e);
89
+ return;
90
+ }
91
+ intervalId = setInterval(checkRealTimersCallback, interval);
92
+ const {
93
+ MutationObserver
94
+ } = (0, _helpers.getWindowFromNode)(container);
95
+ observer = new MutationObserver(checkRealTimersCallback);
96
+ observer.observe(container, mutationObserverOptions);
97
+ checkCallback();
98
+ }
99
+ function onDone(error, result) {
100
+ finished = true;
101
+ clearTimeout(overallTimeoutTimer);
102
+ if (!usingJestFakeTimers) {
103
+ clearInterval(intervalId);
104
+ observer.disconnect();
105
+ }
106
+ if (error) {
107
+ reject(error);
108
+ } else {
109
+ resolve(result);
110
+ }
111
+ }
112
+ function checkRealTimersCallback() {
113
+ if ((0, _helpers.jestFakeTimersAreEnabled)()) {
114
+ const error = new Error(`Changed from using real timers to fake timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to fake timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`);
115
+ if (!showOriginalStackTrace) copyStackTrace(error, stackTraceError);
116
+ return reject(error);
117
+ } else {
118
+ return checkCallback();
119
+ }
120
+ }
121
+ function checkCallback() {
122
+ if (promiseStatus === 'pending') return;
123
+ try {
124
+ const result = (0, _config.runWithExpensiveErrorDiagnosticsDisabled)(callback);
125
+ if (typeof result?.then === 'function') {
126
+ promiseStatus = 'pending';
127
+ result.then(resolvedValue => {
128
+ promiseStatus = 'resolved';
129
+ onDone(null, resolvedValue);
130
+ }, rejectedValue => {
131
+ promiseStatus = 'rejected';
132
+ lastError = rejectedValue;
133
+ });
134
+ } else {
135
+ onDone(null, result);
136
+ }
137
+ // If `callback` throws, wait for the next mutation, interval, or timeout.
138
+ } catch (error) {
139
+ // Save the most recent callback error to reject the promise with it in the event of a timeout
140
+ lastError = error;
141
+ }
142
+ }
143
+ function handleTimeout() {
144
+ let error;
145
+ if (lastError) {
146
+ error = lastError;
147
+ if (!showOriginalStackTrace && error.name === 'TestingLibraryElementError') {
148
+ copyStackTrace(error, stackTraceError);
149
+ }
150
+ } else {
151
+ error = new Error('Timed out in waitFor.');
152
+ if (!showOriginalStackTrace) {
153
+ copyStackTrace(error, stackTraceError);
154
+ }
155
+ }
156
+ onDone(onTimeout(error), null);
157
+ }
158
+ });
159
+ }
160
+ function waitForWrapper(callback, options) {
161
+ // create the error here so its stack trace is as close to the
162
+ // calling code as possible
163
+ const stackTraceError = new Error('STACK_TRACE_MESSAGE');
164
+ return (0, _config.getConfig)().asyncWrapper(() => waitFor(callback, {
165
+ stackTraceError,
166
+ ...options
167
+ }));
168
+ }
169
+
170
+ /*
171
+ eslint
172
+ max-lines-per-function: ["error", {"max": 200}],
173
+ */
node_modules/@testing-library/dom/package.json ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "@testing-library/dom",
3
+ "version": "10.4.1",
4
+ "description": "Simple and complete DOM testing utilities that encourage good testing practices.",
5
+ "main": "dist/index.js",
6
+ "types": "types/index.d.ts",
7
+ "module": "dist/@testing-library/dom.esm.js",
8
+ "umd:main": "dist/@testing-library/dom.umd.js",
9
+ "source": "src/index.js",
10
+ "keywords": [
11
+ "testing",
12
+ "ui",
13
+ "dom",
14
+ "jsdom",
15
+ "unit",
16
+ "integration",
17
+ "functional",
18
+ "end-to-end",
19
+ "e2e"
20
+ ],
21
+ "author": "Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)",
22
+ "license": "MIT",
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "browserslist": [
27
+ "and_chr 103",
28
+ "and_ff 101",
29
+ "and_qq 10.4",
30
+ "and_uc 12.12",
31
+ "android 103",
32
+ "chrome 102",
33
+ "edge 102",
34
+ "firefox 91",
35
+ "ios_saf 12.2-12.5",
36
+ "kaios 2.5",
37
+ "op_mini all",
38
+ "op_mob 64",
39
+ "opera 88",
40
+ "safari 15.5",
41
+ "samsung 17.0",
42
+ "samsung 16.0",
43
+ "node 18.0"
44
+ ],
45
+ "scripts": {
46
+ "build": "kcd-scripts build --no-ts-defs --ignore \"**/__tests__/**,**/__node_tests__/**,**/__mocks__/**\" && kcd-scripts build --no-ts-defs --bundle --no-clean",
47
+ "format": "kcd-scripts format",
48
+ "install:csb": "npm install",
49
+ "lint": "kcd-scripts lint",
50
+ "setup": "npm install && npm run validate -s",
51
+ "test": "kcd-scripts test",
52
+ "test:debug": "node --inspect-brk ./node_modules/.bin/jest --watch --runInBand",
53
+ "test:update": "npm test -- --updateSnapshot --coverage",
54
+ "validate": "kcd-scripts validate",
55
+ "typecheck": "kcd-scripts typecheck --build types"
56
+ },
57
+ "files": [
58
+ "dist",
59
+ "types/*.d.ts"
60
+ ],
61
+ "dependencies": {
62
+ "@babel/code-frame": "^7.10.4",
63
+ "@babel/runtime": "^7.12.5",
64
+ "@types/aria-query": "^5.0.1",
65
+ "aria-query": "5.3.0",
66
+ "dom-accessibility-api": "^0.5.9",
67
+ "lz-string": "^1.5.0",
68
+ "picocolors": "1.1.1",
69
+ "pretty-format": "^27.0.2"
70
+ },
71
+ "devDependencies": {
72
+ "@testing-library/jest-dom": "^5.11.6",
73
+ "browserslist": "4.21.8",
74
+ "caniuse-lite": "1.0.30001502",
75
+ "jest-in-case": "^1.0.2",
76
+ "jest-snapshot-serializer-ansi": "^1.0.0",
77
+ "jest-watch-select-projects": "^2.0.0",
78
+ "jsdom": "20.0.0",
79
+ "kcd-scripts": "^13.0.0",
80
+ "typescript": "^4.1.2"
81
+ },
82
+ "overrides": {
83
+ "@babel/helper-compilation-targets": "7.24.7",
84
+ "browserslist": "4.21.8",
85
+ "caniuse-lite": "1.0.30001502"
86
+ },
87
+ "eslintConfig": {
88
+ "extends": [
89
+ "./node_modules/kcd-scripts/eslint.js",
90
+ "plugin:import/typescript"
91
+ ],
92
+ "parserOptions": {
93
+ "ecmaVersion": 2020
94
+ },
95
+ "rules": {
96
+ "@typescript-eslint/prefer-optional-chain": "off",
97
+ "@typescript-eslint/no-explicit-any": "off",
98
+ "@typescript-eslint/no-unsafe-member-access": "off",
99
+ "@typescript-eslint/no-unnecessary-boolean-literal-compare": "off",
100
+ "@typescript-eslint/prefer-includes": "off",
101
+ "import/prefer-default-export": "off",
102
+ "import/no-unassigned-import": "off",
103
+ "import/no-useless-path-segments": "off",
104
+ "no-console": "off"
105
+ }
106
+ },
107
+ "eslintIgnore": [
108
+ "node_modules",
109
+ "coverage",
110
+ "dist"
111
+ ],
112
+ "repository": {
113
+ "type": "git",
114
+ "url": "https://github.com/testing-library/dom-testing-library"
115
+ },
116
+ "bugs": {
117
+ "url": "https://github.com/testing-library/dom-testing-library/issues"
118
+ },
119
+ "homepage": "https://github.com/testing-library/dom-testing-library#readme"
120
+ }
node_modules/@testing-library/dom/types/config.d.ts ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export interface Config {
2
+ testIdAttribute: string
3
+ /**
4
+ * WARNING: `unstable` prefix means this API may change in patch and minor releases.
5
+ * @param cb
6
+ */
7
+ unstable_advanceTimersWrapper(cb: (...args: unknown[]) => unknown): unknown
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ asyncWrapper(cb: (...args: any[]) => any): Promise<any>
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ eventWrapper(cb: (...args: any[]) => any): void
12
+ asyncUtilTimeout: number
13
+ computedStyleSupportsPseudoElements: boolean
14
+ defaultHidden: boolean
15
+ /** default value for the `ignore` option in `ByText` queries */
16
+ defaultIgnore: string
17
+ showOriginalStackTrace: boolean
18
+ throwSuggestions: boolean
19
+ getElementError: (message: string | null, container: Element) => Error
20
+ }
21
+
22
+ export interface ConfigFn {
23
+ (existingConfig: Config): Partial<Config>
24
+ }
25
+
26
+ export function configure(configDelta: ConfigFn | Partial<Config>): void
27
+ export function getConfig(): Config
node_modules/@testing-library/dom/types/events.d.ts ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export type EventType =
2
+ | 'copy'
3
+ | 'cut'
4
+ | 'paste'
5
+ | 'compositionEnd'
6
+ | 'compositionStart'
7
+ | 'compositionUpdate'
8
+ | 'keyDown'
9
+ | 'keyPress'
10
+ | 'keyUp'
11
+ | 'focus'
12
+ | 'blur'
13
+ | 'focusIn'
14
+ | 'focusOut'
15
+ | 'change'
16
+ | 'input'
17
+ | 'invalid'
18
+ | 'submit'
19
+ | 'reset'
20
+ | 'click'
21
+ | 'contextMenu'
22
+ | 'dblClick'
23
+ | 'drag'
24
+ | 'dragEnd'
25
+ | 'dragEnter'
26
+ | 'dragExit'
27
+ | 'dragLeave'
28
+ | 'dragOver'
29
+ | 'dragStart'
30
+ | 'drop'
31
+ | 'mouseDown'
32
+ | 'mouseEnter'
33
+ | 'mouseLeave'
34
+ | 'mouseMove'
35
+ | 'mouseOut'
36
+ | 'mouseOver'
37
+ | 'mouseUp'
38
+ | 'popState'
39
+ | 'select'
40
+ | 'touchCancel'
41
+ | 'touchEnd'
42
+ | 'touchMove'
43
+ | 'touchStart'
44
+ | 'resize'
45
+ | 'scroll'
46
+ | 'wheel'
47
+ | 'abort'
48
+ | 'canPlay'
49
+ | 'canPlayThrough'
50
+ | 'durationChange'
51
+ | 'emptied'
52
+ | 'encrypted'
53
+ | 'ended'
54
+ | 'loadedData'
55
+ | 'loadedMetadata'
56
+ | 'loadStart'
57
+ | 'pause'
58
+ | 'play'
59
+ | 'playing'
60
+ | 'progress'
61
+ | 'rateChange'
62
+ | 'seeked'
63
+ | 'seeking'
64
+ | 'stalled'
65
+ | 'suspend'
66
+ | 'timeUpdate'
67
+ | 'volumeChange'
68
+ | 'waiting'
69
+ | 'load'
70
+ | 'error'
71
+ | 'animationStart'
72
+ | 'animationEnd'
73
+ | 'animationIteration'
74
+ | 'transitionCancel'
75
+ | 'transitionEnd'
76
+ | 'transitionRun'
77
+ | 'transitionStart'
78
+ | 'doubleClick'
79
+ | 'pointerOver'
80
+ | 'pointerEnter'
81
+ | 'pointerDown'
82
+ | 'pointerMove'
83
+ | 'pointerUp'
84
+ | 'pointerCancel'
85
+ | 'pointerOut'
86
+ | 'pointerLeave'
87
+ | 'gotPointerCapture'
88
+ | 'lostPointerCapture'
89
+ | 'offline'
90
+ | 'online'
91
+ | 'pageHide'
92
+ | 'pageShow'
93
+
94
+ export type FireFunction = (
95
+ element: Document | Element | Window | Node,
96
+ event: Event,
97
+ ) => boolean
98
+ export type FireObject = {
99
+ [K in EventType]: (
100
+ element: Document | Element | Window | Node,
101
+ options?: {},
102
+ ) => boolean
103
+ }
104
+ export type CreateFunction = (
105
+ eventName: string,
106
+ node: Document | Element | Window | Node,
107
+ init?: {},
108
+ options?: {EventType?: string; defaultInit?: {}},
109
+ ) => Event
110
+ export type CreateObject = {
111
+ [K in EventType]: (
112
+ element: Document | Element | Window | Node,
113
+ options?: {},
114
+ ) => Event
115
+ }
116
+
117
+ export const createEvent: CreateObject & CreateFunction
118
+ export const fireEvent: FireFunction & FireObject
node_modules/@testing-library/dom/types/get-node-text.d.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ export function getNodeText(node: HTMLElement): string