├── .eslintrc.json ├── .github ├── eslint.json └── workflows │ └── node.js.yml ├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── rollup.config.js ├── src ├── active.js ├── index.js ├── interrupt.js ├── selection │ ├── index.js │ ├── interrupt.js │ └── transition.js └── transition │ ├── attr.js │ ├── attrTween.js │ ├── delay.js │ ├── duration.js │ ├── ease.js │ ├── easeVarying.js │ ├── end.js │ ├── filter.js │ ├── index.js │ ├── interpolate.js │ ├── merge.js │ ├── on.js │ ├── remove.js │ ├── schedule.js │ ├── select.js │ ├── selectAll.js │ ├── selection.js │ ├── style.js │ ├── styleTween.js │ ├── text.js │ ├── textTween.js │ ├── transition.js │ └── tween.js ├── test ├── .eslintrc.json ├── active-test.js ├── error-test.js ├── interrupt-test.js ├── jsdom.js ├── selection │ ├── interrupt-test.js │ └── transition-test.js └── transition │ ├── attr-test.js │ ├── attrTween-test.js │ ├── call-test.js │ ├── delay-test.js │ ├── duration-test.js │ ├── each-test.js │ ├── ease-test.js │ ├── easeVarying-test.js │ ├── empty-test.js │ ├── filter-test.js │ ├── index-test.js │ ├── merge-test.js │ ├── node-test.js │ ├── nodes-test.js │ ├── on-test.js │ ├── remove-test.js │ ├── select-test.js │ ├── selectAll-test.js │ ├── selectChild-test.js │ ├── selectChildren-test.js │ ├── selection-test.js │ ├── size-test.js │ ├── style-test.js │ ├── styleTween-test.js │ ├── text-test.js │ ├── textTween-test.js │ ├── transition-test.js │ └── tween-test.js └── yarn.lock /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "parserOptions": { 4 | "sourceType": "module", 5 | "ecmaVersion": 8 6 | }, 7 | "env": { 8 | "es6": true 9 | }, 10 | "rules": { 11 | "no-cond-assign": 0 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.github/eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "problemMatcher": [ 3 | { 4 | "owner": "eslint-compact", 5 | "pattern": [ 6 | { 7 | "regexp": "^(.+):\\sline\\s(\\d+),\\scol\\s(\\d+),\\s(Error|Warning|Info)\\s-\\s(.+)\\s\\((.+)\\)$", 8 | "file": 1, 9 | "line": 2, 10 | "column": 3, 11 | "severity": 4, 12 | "message": 5, 13 | "code": 6 14 | } 15 | ] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 2 | 3 | name: Node.js CI 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | pull_request: 9 | branches: [ main ] 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [14.x] 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v1 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | - run: yarn --frozen-lockfile 27 | - run: | 28 | echo ::add-matcher::.github/eslint.json 29 | yarn run eslint src test --format=compact 30 | - run: yarn test 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sublime-workspace 2 | .DS_Store 3 | dist/ 4 | node_modules 5 | npm-debug.log 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010-2021 Mike Bostock 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose 4 | with or without fee is hereby granted, provided that the above copyright notice 5 | and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 11 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 12 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 13 | THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # d3-transition 2 | 3 | 4 | 5 | A transition is a [selection](https://github.com/d3/d3-selection)-like interface for animating changes to the DOM. Instead of applying changes instantaneously, transitions smoothly interpolate the DOM from its current state to the desired target state over a given duration. 6 | 7 | ## Resources 8 | 9 | - [Documentation](https://d3js.org/d3-transition) 10 | - [Examples](https://observablehq.com/collection/@d3/d3-transition) 11 | - [Releases](https://github.com/d3/d3-transition/releases) 12 | - [Getting help](https://d3js.org/community) 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d3-transition", 3 | "version": "3.0.1", 4 | "description": "Animated transitions for D3 selections.", 5 | "homepage": "https://d3js.org/d3-transition/", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/d3/d3-transition.git" 9 | }, 10 | "keywords": [ 11 | "d3", 12 | "d3-module", 13 | "dom", 14 | "transition", 15 | "animation" 16 | ], 17 | "license": "ISC", 18 | "author": { 19 | "name": "Mike Bostock", 20 | "url": "https://bost.ocks.org/mike" 21 | }, 22 | "type": "module", 23 | "files": [ 24 | "dist/**/*.js", 25 | "src/**/*.js" 26 | ], 27 | "module": "src/index.js", 28 | "main": "src/index.js", 29 | "jsdelivr": "dist/d3-transition.min.js", 30 | "unpkg": "dist/d3-transition.min.js", 31 | "exports": { 32 | "umd": "./dist/d3-transition.min.js", 33 | "default": "./src/index.js" 34 | }, 35 | "sideEffects": [ 36 | "./src/index.js", 37 | "./src/selection/index.js" 38 | ], 39 | "dependencies": { 40 | "d3-color": "1 - 3", 41 | "d3-dispatch": "1 - 3", 42 | "d3-ease": "1 - 3", 43 | "d3-interpolate": "1 - 3", 44 | "d3-timer": "1 - 3" 45 | }, 46 | "devDependencies": { 47 | "d3-selection": "2 - 3", 48 | "eslint": "7", 49 | "jsdom": "16", 50 | "mocha": "9", 51 | "rollup": "2", 52 | "rollup-plugin-terser": "7" 53 | }, 54 | "scripts": { 55 | "test": "mocha 'test/**/*-test.js' && eslint src test", 56 | "prepublishOnly": "rm -rf dist && yarn test && rollup -c && git push", 57 | "postpublish": "git push --tags && cd ../d3.github.com && git pull && cp ../${npm_package_name}/dist/${npm_package_name}.js ${npm_package_name}.v${npm_package_version%%.*}.js && cp ../${npm_package_name}/dist/${npm_package_name}.min.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git add ${npm_package_name}.v${npm_package_version%%.*}.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git commit -m \"${npm_package_name} ${npm_package_version}\" && git push && cd -" 58 | }, 59 | "engines": { 60 | "node": ">=12" 61 | }, 62 | "peerDependencies": { 63 | "d3-selection": "2 - 3" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import {readFileSync} from "fs"; 2 | import {terser} from "rollup-plugin-terser"; 3 | import * as meta from "./package.json"; 4 | 5 | // Extract copyrights from the LICENSE. 6 | const copyright = readFileSync("./LICENSE", "utf-8") 7 | .split(/\n/g) 8 | .filter(line => /^Copyright\s+/.test(line)) 9 | .map(line => line.replace(/^Copyright\s+/, "")) 10 | .join(", "); 11 | 12 | const config = { 13 | input: "src/index.js", 14 | external: Object.keys({...meta.dependencies, ...meta.peerDependencies}).filter(key => /^d3-/.test(key)), 15 | output: { 16 | file: `dist/${meta.name}.js`, 17 | name: "d3", 18 | format: "umd", 19 | indent: false, 20 | extend: true, 21 | banner: `// ${meta.homepage} v${meta.version} Copyright ${copyright}`, 22 | globals: Object.assign({}, ...Object.keys({...meta.dependencies, ...meta.peerDependencies}).filter(key => /^d3-/.test(key)).map(key => ({[key]: "d3"}))) 23 | }, 24 | plugins: [], 25 | onwarn(message, warn) { 26 | if (message.code === "CIRCULAR_DEPENDENCY") return; 27 | warn(message); 28 | } 29 | }; 30 | 31 | export default [ 32 | config, 33 | { 34 | ...config, 35 | output: { 36 | ...config.output, 37 | file: `dist/${meta.name}.min.js` 38 | }, 39 | plugins: [ 40 | ...config.plugins, 41 | terser({ 42 | output: { 43 | preamble: config.output.banner 44 | } 45 | }) 46 | ] 47 | } 48 | ]; 49 | -------------------------------------------------------------------------------- /src/active.js: -------------------------------------------------------------------------------- 1 | import {Transition} from "./transition/index.js"; 2 | import {SCHEDULED} from "./transition/schedule.js"; 3 | 4 | var root = [null]; 5 | 6 | export default function(node, name) { 7 | var schedules = node.__transition, 8 | schedule, 9 | i; 10 | 11 | if (schedules) { 12 | name = name == null ? null : name + ""; 13 | for (i in schedules) { 14 | if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) { 15 | return new Transition([[node]], root, name, +i); 16 | } 17 | } 18 | } 19 | 20 | return null; 21 | } 22 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import "./selection/index.js"; 2 | export {default as transition} from "./transition/index.js"; 3 | export {default as active} from "./active.js"; 4 | export {default as interrupt} from "./interrupt.js"; 5 | -------------------------------------------------------------------------------- /src/interrupt.js: -------------------------------------------------------------------------------- 1 | import {STARTING, ENDING, ENDED} from "./transition/schedule.js"; 2 | 3 | export default function(node, name) { 4 | var schedules = node.__transition, 5 | schedule, 6 | active, 7 | empty = true, 8 | i; 9 | 10 | if (!schedules) return; 11 | 12 | name = name == null ? null : name + ""; 13 | 14 | for (i in schedules) { 15 | if ((schedule = schedules[i]).name !== name) { empty = false; continue; } 16 | active = schedule.state > STARTING && schedule.state < ENDING; 17 | schedule.state = ENDED; 18 | schedule.timer.stop(); 19 | schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group); 20 | delete schedules[i]; 21 | } 22 | 23 | if (empty) delete node.__transition; 24 | } 25 | -------------------------------------------------------------------------------- /src/selection/index.js: -------------------------------------------------------------------------------- 1 | import {selection} from "d3-selection"; 2 | import selection_interrupt from "./interrupt.js"; 3 | import selection_transition from "./transition.js"; 4 | 5 | selection.prototype.interrupt = selection_interrupt; 6 | selection.prototype.transition = selection_transition; 7 | -------------------------------------------------------------------------------- /src/selection/interrupt.js: -------------------------------------------------------------------------------- 1 | import interrupt from "../interrupt.js"; 2 | 3 | export default function(name) { 4 | return this.each(function() { 5 | interrupt(this, name); 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /src/selection/transition.js: -------------------------------------------------------------------------------- 1 | import {Transition, newId} from "../transition/index.js"; 2 | import schedule from "../transition/schedule.js"; 3 | import {easeCubicInOut} from "d3-ease"; 4 | import {now} from "d3-timer"; 5 | 6 | var defaultTiming = { 7 | time: null, // Set on use. 8 | delay: 0, 9 | duration: 250, 10 | ease: easeCubicInOut 11 | }; 12 | 13 | function inherit(node, id) { 14 | var timing; 15 | while (!(timing = node.__transition) || !(timing = timing[id])) { 16 | if (!(node = node.parentNode)) { 17 | throw new Error(`transition ${id} not found`); 18 | } 19 | } 20 | return timing; 21 | } 22 | 23 | export default function(name) { 24 | var id, 25 | timing; 26 | 27 | if (name instanceof Transition) { 28 | id = name._id, name = name._name; 29 | } else { 30 | id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; 31 | } 32 | 33 | for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { 34 | for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { 35 | if (node = group[i]) { 36 | schedule(node, name, id, i, group, timing || inherit(node, id)); 37 | } 38 | } 39 | } 40 | 41 | return new Transition(groups, this._parents, name, id); 42 | } 43 | -------------------------------------------------------------------------------- /src/transition/attr.js: -------------------------------------------------------------------------------- 1 | import {interpolateTransformSvg as interpolateTransform} from "d3-interpolate"; 2 | import {namespace} from "d3-selection"; 3 | import {tweenValue} from "./tween.js"; 4 | import interpolate from "./interpolate.js"; 5 | 6 | function attrRemove(name) { 7 | return function() { 8 | this.removeAttribute(name); 9 | }; 10 | } 11 | 12 | function attrRemoveNS(fullname) { 13 | return function() { 14 | this.removeAttributeNS(fullname.space, fullname.local); 15 | }; 16 | } 17 | 18 | function attrConstant(name, interpolate, value1) { 19 | var string00, 20 | string1 = value1 + "", 21 | interpolate0; 22 | return function() { 23 | var string0 = this.getAttribute(name); 24 | return string0 === string1 ? null 25 | : string0 === string00 ? interpolate0 26 | : interpolate0 = interpolate(string00 = string0, value1); 27 | }; 28 | } 29 | 30 | function attrConstantNS(fullname, interpolate, value1) { 31 | var string00, 32 | string1 = value1 + "", 33 | interpolate0; 34 | return function() { 35 | var string0 = this.getAttributeNS(fullname.space, fullname.local); 36 | return string0 === string1 ? null 37 | : string0 === string00 ? interpolate0 38 | : interpolate0 = interpolate(string00 = string0, value1); 39 | }; 40 | } 41 | 42 | function attrFunction(name, interpolate, value) { 43 | var string00, 44 | string10, 45 | interpolate0; 46 | return function() { 47 | var string0, value1 = value(this), string1; 48 | if (value1 == null) return void this.removeAttribute(name); 49 | string0 = this.getAttribute(name); 50 | string1 = value1 + ""; 51 | return string0 === string1 ? null 52 | : string0 === string00 && string1 === string10 ? interpolate0 53 | : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); 54 | }; 55 | } 56 | 57 | function attrFunctionNS(fullname, interpolate, value) { 58 | var string00, 59 | string10, 60 | interpolate0; 61 | return function() { 62 | var string0, value1 = value(this), string1; 63 | if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); 64 | string0 = this.getAttributeNS(fullname.space, fullname.local); 65 | string1 = value1 + ""; 66 | return string0 === string1 ? null 67 | : string0 === string00 && string1 === string10 ? interpolate0 68 | : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); 69 | }; 70 | } 71 | 72 | export default function(name, value) { 73 | var fullname = namespace(name), i = fullname === "transform" ? interpolateTransform : interpolate; 74 | return this.attrTween(name, typeof value === "function" 75 | ? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) 76 | : value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) 77 | : (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value)); 78 | } 79 | -------------------------------------------------------------------------------- /src/transition/attrTween.js: -------------------------------------------------------------------------------- 1 | import {namespace} from "d3-selection"; 2 | 3 | function attrInterpolate(name, i) { 4 | return function(t) { 5 | this.setAttribute(name, i.call(this, t)); 6 | }; 7 | } 8 | 9 | function attrInterpolateNS(fullname, i) { 10 | return function(t) { 11 | this.setAttributeNS(fullname.space, fullname.local, i.call(this, t)); 12 | }; 13 | } 14 | 15 | function attrTweenNS(fullname, value) { 16 | var t0, i0; 17 | function tween() { 18 | var i = value.apply(this, arguments); 19 | if (i !== i0) t0 = (i0 = i) && attrInterpolateNS(fullname, i); 20 | return t0; 21 | } 22 | tween._value = value; 23 | return tween; 24 | } 25 | 26 | function attrTween(name, value) { 27 | var t0, i0; 28 | function tween() { 29 | var i = value.apply(this, arguments); 30 | if (i !== i0) t0 = (i0 = i) && attrInterpolate(name, i); 31 | return t0; 32 | } 33 | tween._value = value; 34 | return tween; 35 | } 36 | 37 | export default function(name, value) { 38 | var key = "attr." + name; 39 | if (arguments.length < 2) return (key = this.tween(key)) && key._value; 40 | if (value == null) return this.tween(key, null); 41 | if (typeof value !== "function") throw new Error; 42 | var fullname = namespace(name); 43 | return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); 44 | } 45 | -------------------------------------------------------------------------------- /src/transition/delay.js: -------------------------------------------------------------------------------- 1 | import {get, init} from "./schedule.js"; 2 | 3 | function delayFunction(id, value) { 4 | return function() { 5 | init(this, id).delay = +value.apply(this, arguments); 6 | }; 7 | } 8 | 9 | function delayConstant(id, value) { 10 | return value = +value, function() { 11 | init(this, id).delay = value; 12 | }; 13 | } 14 | 15 | export default function(value) { 16 | var id = this._id; 17 | 18 | return arguments.length 19 | ? this.each((typeof value === "function" 20 | ? delayFunction 21 | : delayConstant)(id, value)) 22 | : get(this.node(), id).delay; 23 | } 24 | -------------------------------------------------------------------------------- /src/transition/duration.js: -------------------------------------------------------------------------------- 1 | import {get, set} from "./schedule.js"; 2 | 3 | function durationFunction(id, value) { 4 | return function() { 5 | set(this, id).duration = +value.apply(this, arguments); 6 | }; 7 | } 8 | 9 | function durationConstant(id, value) { 10 | return value = +value, function() { 11 | set(this, id).duration = value; 12 | }; 13 | } 14 | 15 | export default function(value) { 16 | var id = this._id; 17 | 18 | return arguments.length 19 | ? this.each((typeof value === "function" 20 | ? durationFunction 21 | : durationConstant)(id, value)) 22 | : get(this.node(), id).duration; 23 | } 24 | -------------------------------------------------------------------------------- /src/transition/ease.js: -------------------------------------------------------------------------------- 1 | import {get, set} from "./schedule.js"; 2 | 3 | function easeConstant(id, value) { 4 | if (typeof value !== "function") throw new Error; 5 | return function() { 6 | set(this, id).ease = value; 7 | }; 8 | } 9 | 10 | export default function(value) { 11 | var id = this._id; 12 | 13 | return arguments.length 14 | ? this.each(easeConstant(id, value)) 15 | : get(this.node(), id).ease; 16 | } 17 | -------------------------------------------------------------------------------- /src/transition/easeVarying.js: -------------------------------------------------------------------------------- 1 | import {set} from "./schedule.js"; 2 | 3 | function easeVarying(id, value) { 4 | return function() { 5 | var v = value.apply(this, arguments); 6 | if (typeof v !== "function") throw new Error; 7 | set(this, id).ease = v; 8 | }; 9 | } 10 | 11 | export default function(value) { 12 | if (typeof value !== "function") throw new Error; 13 | return this.each(easeVarying(this._id, value)); 14 | } 15 | -------------------------------------------------------------------------------- /src/transition/end.js: -------------------------------------------------------------------------------- 1 | import {set} from "./schedule.js"; 2 | 3 | export default function() { 4 | var on0, on1, that = this, id = that._id, size = that.size(); 5 | return new Promise(function(resolve, reject) { 6 | var cancel = {value: reject}, 7 | end = {value: function() { if (--size === 0) resolve(); }}; 8 | 9 | that.each(function() { 10 | var schedule = set(this, id), 11 | on = schedule.on; 12 | 13 | // If this node shared a dispatch with the previous node, 14 | // just assign the updated shared dispatch and we’re done! 15 | // Otherwise, copy-on-write. 16 | if (on !== on0) { 17 | on1 = (on0 = on).copy(); 18 | on1._.cancel.push(cancel); 19 | on1._.interrupt.push(cancel); 20 | on1._.end.push(end); 21 | } 22 | 23 | schedule.on = on1; 24 | }); 25 | 26 | // The selection was empty, resolve end immediately 27 | if (size === 0) resolve(); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /src/transition/filter.js: -------------------------------------------------------------------------------- 1 | import {matcher} from "d3-selection"; 2 | import {Transition} from "./index.js"; 3 | 4 | export default function(match) { 5 | if (typeof match !== "function") match = matcher(match); 6 | 7 | for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { 8 | for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { 9 | if ((node = group[i]) && match.call(node, node.__data__, i, group)) { 10 | subgroup.push(node); 11 | } 12 | } 13 | } 14 | 15 | return new Transition(subgroups, this._parents, this._name, this._id); 16 | } 17 | -------------------------------------------------------------------------------- /src/transition/index.js: -------------------------------------------------------------------------------- 1 | import {selection} from "d3-selection"; 2 | import transition_attr from "./attr.js"; 3 | import transition_attrTween from "./attrTween.js"; 4 | import transition_delay from "./delay.js"; 5 | import transition_duration from "./duration.js"; 6 | import transition_ease from "./ease.js"; 7 | import transition_easeVarying from "./easeVarying.js"; 8 | import transition_filter from "./filter.js"; 9 | import transition_merge from "./merge.js"; 10 | import transition_on from "./on.js"; 11 | import transition_remove from "./remove.js"; 12 | import transition_select from "./select.js"; 13 | import transition_selectAll from "./selectAll.js"; 14 | import transition_selection from "./selection.js"; 15 | import transition_style from "./style.js"; 16 | import transition_styleTween from "./styleTween.js"; 17 | import transition_text from "./text.js"; 18 | import transition_textTween from "./textTween.js"; 19 | import transition_transition from "./transition.js"; 20 | import transition_tween from "./tween.js"; 21 | import transition_end from "./end.js"; 22 | 23 | var id = 0; 24 | 25 | export function Transition(groups, parents, name, id) { 26 | this._groups = groups; 27 | this._parents = parents; 28 | this._name = name; 29 | this._id = id; 30 | } 31 | 32 | export default function transition(name) { 33 | return selection().transition(name); 34 | } 35 | 36 | export function newId() { 37 | return ++id; 38 | } 39 | 40 | var selection_prototype = selection.prototype; 41 | 42 | Transition.prototype = transition.prototype = { 43 | constructor: Transition, 44 | select: transition_select, 45 | selectAll: transition_selectAll, 46 | selectChild: selection_prototype.selectChild, 47 | selectChildren: selection_prototype.selectChildren, 48 | filter: transition_filter, 49 | merge: transition_merge, 50 | selection: transition_selection, 51 | transition: transition_transition, 52 | call: selection_prototype.call, 53 | nodes: selection_prototype.nodes, 54 | node: selection_prototype.node, 55 | size: selection_prototype.size, 56 | empty: selection_prototype.empty, 57 | each: selection_prototype.each, 58 | on: transition_on, 59 | attr: transition_attr, 60 | attrTween: transition_attrTween, 61 | style: transition_style, 62 | styleTween: transition_styleTween, 63 | text: transition_text, 64 | textTween: transition_textTween, 65 | remove: transition_remove, 66 | tween: transition_tween, 67 | delay: transition_delay, 68 | duration: transition_duration, 69 | ease: transition_ease, 70 | easeVarying: transition_easeVarying, 71 | end: transition_end, 72 | [Symbol.iterator]: selection_prototype[Symbol.iterator] 73 | }; 74 | -------------------------------------------------------------------------------- /src/transition/interpolate.js: -------------------------------------------------------------------------------- 1 | import {color} from "d3-color"; 2 | import {interpolateNumber, interpolateRgb, interpolateString} from "d3-interpolate"; 3 | 4 | export default function(a, b) { 5 | var c; 6 | return (typeof b === "number" ? interpolateNumber 7 | : b instanceof color ? interpolateRgb 8 | : (c = color(b)) ? (b = c, interpolateRgb) 9 | : interpolateString)(a, b); 10 | } 11 | -------------------------------------------------------------------------------- /src/transition/merge.js: -------------------------------------------------------------------------------- 1 | import {Transition} from "./index.js"; 2 | 3 | export default function(transition) { 4 | if (transition._id !== this._id) throw new Error; 5 | 6 | for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { 7 | for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { 8 | if (node = group0[i] || group1[i]) { 9 | merge[i] = node; 10 | } 11 | } 12 | } 13 | 14 | for (; j < m0; ++j) { 15 | merges[j] = groups0[j]; 16 | } 17 | 18 | return new Transition(merges, this._parents, this._name, this._id); 19 | } 20 | -------------------------------------------------------------------------------- /src/transition/on.js: -------------------------------------------------------------------------------- 1 | import {get, set, init} from "./schedule.js"; 2 | 3 | function start(name) { 4 | return (name + "").trim().split(/^|\s+/).every(function(t) { 5 | var i = t.indexOf("."); 6 | if (i >= 0) t = t.slice(0, i); 7 | return !t || t === "start"; 8 | }); 9 | } 10 | 11 | function onFunction(id, name, listener) { 12 | var on0, on1, sit = start(name) ? init : set; 13 | return function() { 14 | var schedule = sit(this, id), 15 | on = schedule.on; 16 | 17 | // If this node shared a dispatch with the previous node, 18 | // just assign the updated shared dispatch and we’re done! 19 | // Otherwise, copy-on-write. 20 | if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); 21 | 22 | schedule.on = on1; 23 | }; 24 | } 25 | 26 | export default function(name, listener) { 27 | var id = this._id; 28 | 29 | return arguments.length < 2 30 | ? get(this.node(), id).on.on(name) 31 | : this.each(onFunction(id, name, listener)); 32 | } 33 | -------------------------------------------------------------------------------- /src/transition/remove.js: -------------------------------------------------------------------------------- 1 | function removeFunction(id) { 2 | return function() { 3 | var parent = this.parentNode; 4 | for (var i in this.__transition) if (+i !== id) return; 5 | if (parent) parent.removeChild(this); 6 | }; 7 | } 8 | 9 | export default function() { 10 | return this.on("end.remove", removeFunction(this._id)); 11 | } 12 | -------------------------------------------------------------------------------- /src/transition/schedule.js: -------------------------------------------------------------------------------- 1 | import {dispatch} from "d3-dispatch"; 2 | import {timer, timeout} from "d3-timer"; 3 | 4 | var emptyOn = dispatch("start", "end", "cancel", "interrupt"); 5 | var emptyTween = []; 6 | 7 | export var CREATED = 0; 8 | export var SCHEDULED = 1; 9 | export var STARTING = 2; 10 | export var STARTED = 3; 11 | export var RUNNING = 4; 12 | export var ENDING = 5; 13 | export var ENDED = 6; 14 | 15 | export default function(node, name, id, index, group, timing) { 16 | var schedules = node.__transition; 17 | if (!schedules) node.__transition = {}; 18 | else if (id in schedules) return; 19 | create(node, id, { 20 | name: name, 21 | index: index, // For context during callback. 22 | group: group, // For context during callback. 23 | on: emptyOn, 24 | tween: emptyTween, 25 | time: timing.time, 26 | delay: timing.delay, 27 | duration: timing.duration, 28 | ease: timing.ease, 29 | timer: null, 30 | state: CREATED 31 | }); 32 | } 33 | 34 | export function init(node, id) { 35 | var schedule = get(node, id); 36 | if (schedule.state > CREATED) throw new Error("too late; already scheduled"); 37 | return schedule; 38 | } 39 | 40 | export function set(node, id) { 41 | var schedule = get(node, id); 42 | if (schedule.state > STARTED) throw new Error("too late; already running"); 43 | return schedule; 44 | } 45 | 46 | export function get(node, id) { 47 | var schedule = node.__transition; 48 | if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found"); 49 | return schedule; 50 | } 51 | 52 | function create(node, id, self) { 53 | var schedules = node.__transition, 54 | tween; 55 | 56 | // Initialize the self timer when the transition is created. 57 | // Note the actual delay is not known until the first callback! 58 | schedules[id] = self; 59 | self.timer = timer(schedule, 0, self.time); 60 | 61 | function schedule(elapsed) { 62 | self.state = SCHEDULED; 63 | self.timer.restart(start, self.delay, self.time); 64 | 65 | // If the elapsed delay is less than our first sleep, start immediately. 66 | if (self.delay <= elapsed) start(elapsed - self.delay); 67 | } 68 | 69 | function start(elapsed) { 70 | var i, j, n, o; 71 | 72 | // If the state is not SCHEDULED, then we previously errored on start. 73 | if (self.state !== SCHEDULED) return stop(); 74 | 75 | for (i in schedules) { 76 | o = schedules[i]; 77 | if (o.name !== self.name) continue; 78 | 79 | // While this element already has a starting transition during this frame, 80 | // defer starting an interrupting transition until that transition has a 81 | // chance to tick (and possibly end); see d3/d3-transition#54! 82 | if (o.state === STARTED) return timeout(start); 83 | 84 | // Interrupt the active transition, if any. 85 | if (o.state === RUNNING) { 86 | o.state = ENDED; 87 | o.timer.stop(); 88 | o.on.call("interrupt", node, node.__data__, o.index, o.group); 89 | delete schedules[i]; 90 | } 91 | 92 | // Cancel any pre-empted transitions. 93 | else if (+i < id) { 94 | o.state = ENDED; 95 | o.timer.stop(); 96 | o.on.call("cancel", node, node.__data__, o.index, o.group); 97 | delete schedules[i]; 98 | } 99 | } 100 | 101 | // Defer the first tick to end of the current frame; see d3/d3#1576. 102 | // Note the transition may be canceled after start and before the first tick! 103 | // Note this must be scheduled before the start event; see d3/d3-transition#16! 104 | // Assuming this is successful, subsequent callbacks go straight to tick. 105 | timeout(function() { 106 | if (self.state === STARTED) { 107 | self.state = RUNNING; 108 | self.timer.restart(tick, self.delay, self.time); 109 | tick(elapsed); 110 | } 111 | }); 112 | 113 | // Dispatch the start event. 114 | // Note this must be done before the tween are initialized. 115 | self.state = STARTING; 116 | self.on.call("start", node, node.__data__, self.index, self.group); 117 | if (self.state !== STARTING) return; // interrupted 118 | self.state = STARTED; 119 | 120 | // Initialize the tween, deleting null tween. 121 | tween = new Array(n = self.tween.length); 122 | for (i = 0, j = -1; i < n; ++i) { 123 | if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { 124 | tween[++j] = o; 125 | } 126 | } 127 | tween.length = j + 1; 128 | } 129 | 130 | function tick(elapsed) { 131 | var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), 132 | i = -1, 133 | n = tween.length; 134 | 135 | while (++i < n) { 136 | tween[i].call(node, t); 137 | } 138 | 139 | // Dispatch the end event. 140 | if (self.state === ENDING) { 141 | self.on.call("end", node, node.__data__, self.index, self.group); 142 | stop(); 143 | } 144 | } 145 | 146 | function stop() { 147 | self.state = ENDED; 148 | self.timer.stop(); 149 | delete schedules[id]; 150 | for (var i in schedules) return; // eslint-disable-line no-unused-vars 151 | delete node.__transition; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/transition/select.js: -------------------------------------------------------------------------------- 1 | import {selector} from "d3-selection"; 2 | import {Transition} from "./index.js"; 3 | import schedule, {get} from "./schedule.js"; 4 | 5 | export default function(select) { 6 | var name = this._name, 7 | id = this._id; 8 | 9 | if (typeof select !== "function") select = selector(select); 10 | 11 | for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { 12 | for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { 13 | if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { 14 | if ("__data__" in node) subnode.__data__ = node.__data__; 15 | subgroup[i] = subnode; 16 | schedule(subgroup[i], name, id, i, subgroup, get(node, id)); 17 | } 18 | } 19 | } 20 | 21 | return new Transition(subgroups, this._parents, name, id); 22 | } 23 | -------------------------------------------------------------------------------- /src/transition/selectAll.js: -------------------------------------------------------------------------------- 1 | import {selectorAll} from "d3-selection"; 2 | import {Transition} from "./index.js"; 3 | import schedule, {get} from "./schedule.js"; 4 | 5 | export default function(select) { 6 | var name = this._name, 7 | id = this._id; 8 | 9 | if (typeof select !== "function") select = selectorAll(select); 10 | 11 | for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { 12 | for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { 13 | if (node = group[i]) { 14 | for (var children = select.call(node, node.__data__, i, group), child, inherit = get(node, id), k = 0, l = children.length; k < l; ++k) { 15 | if (child = children[k]) { 16 | schedule(child, name, id, k, children, inherit); 17 | } 18 | } 19 | subgroups.push(children); 20 | parents.push(node); 21 | } 22 | } 23 | } 24 | 25 | return new Transition(subgroups, parents, name, id); 26 | } 27 | -------------------------------------------------------------------------------- /src/transition/selection.js: -------------------------------------------------------------------------------- 1 | import {selection} from "d3-selection"; 2 | 3 | var Selection = selection.prototype.constructor; 4 | 5 | export default function() { 6 | return new Selection(this._groups, this._parents); 7 | } 8 | -------------------------------------------------------------------------------- /src/transition/style.js: -------------------------------------------------------------------------------- 1 | import {interpolateTransformCss as interpolateTransform} from "d3-interpolate"; 2 | import {style} from "d3-selection"; 3 | import {set} from "./schedule.js"; 4 | import {tweenValue} from "./tween.js"; 5 | import interpolate from "./interpolate.js"; 6 | 7 | function styleNull(name, interpolate) { 8 | var string00, 9 | string10, 10 | interpolate0; 11 | return function() { 12 | var string0 = style(this, name), 13 | string1 = (this.style.removeProperty(name), style(this, name)); 14 | return string0 === string1 ? null 15 | : string0 === string00 && string1 === string10 ? interpolate0 16 | : interpolate0 = interpolate(string00 = string0, string10 = string1); 17 | }; 18 | } 19 | 20 | function styleRemove(name) { 21 | return function() { 22 | this.style.removeProperty(name); 23 | }; 24 | } 25 | 26 | function styleConstant(name, interpolate, value1) { 27 | var string00, 28 | string1 = value1 + "", 29 | interpolate0; 30 | return function() { 31 | var string0 = style(this, name); 32 | return string0 === string1 ? null 33 | : string0 === string00 ? interpolate0 34 | : interpolate0 = interpolate(string00 = string0, value1); 35 | }; 36 | } 37 | 38 | function styleFunction(name, interpolate, value) { 39 | var string00, 40 | string10, 41 | interpolate0; 42 | return function() { 43 | var string0 = style(this, name), 44 | value1 = value(this), 45 | string1 = value1 + ""; 46 | if (value1 == null) string1 = value1 = (this.style.removeProperty(name), style(this, name)); 47 | return string0 === string1 ? null 48 | : string0 === string00 && string1 === string10 ? interpolate0 49 | : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); 50 | }; 51 | } 52 | 53 | function styleMaybeRemove(id, name) { 54 | var on0, on1, listener0, key = "style." + name, event = "end." + key, remove; 55 | return function() { 56 | var schedule = set(this, id), 57 | on = schedule.on, 58 | listener = schedule.value[key] == null ? remove || (remove = styleRemove(name)) : undefined; 59 | 60 | // If this node shared a dispatch with the previous node, 61 | // just assign the updated shared dispatch and we’re done! 62 | // Otherwise, copy-on-write. 63 | if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener); 64 | 65 | schedule.on = on1; 66 | }; 67 | } 68 | 69 | export default function(name, value, priority) { 70 | var i = (name += "") === "transform" ? interpolateTransform : interpolate; 71 | return value == null ? this 72 | .styleTween(name, styleNull(name, i)) 73 | .on("end.style." + name, styleRemove(name)) 74 | : typeof value === "function" ? this 75 | .styleTween(name, styleFunction(name, i, tweenValue(this, "style." + name, value))) 76 | .each(styleMaybeRemove(this._id, name)) 77 | : this 78 | .styleTween(name, styleConstant(name, i, value), priority) 79 | .on("end.style." + name, null); 80 | } 81 | -------------------------------------------------------------------------------- /src/transition/styleTween.js: -------------------------------------------------------------------------------- 1 | function styleInterpolate(name, i, priority) { 2 | return function(t) { 3 | this.style.setProperty(name, i.call(this, t), priority); 4 | }; 5 | } 6 | 7 | function styleTween(name, value, priority) { 8 | var t, i0; 9 | function tween() { 10 | var i = value.apply(this, arguments); 11 | if (i !== i0) t = (i0 = i) && styleInterpolate(name, i, priority); 12 | return t; 13 | } 14 | tween._value = value; 15 | return tween; 16 | } 17 | 18 | export default function(name, value, priority) { 19 | var key = "style." + (name += ""); 20 | if (arguments.length < 2) return (key = this.tween(key)) && key._value; 21 | if (value == null) return this.tween(key, null); 22 | if (typeof value !== "function") throw new Error; 23 | return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); 24 | } 25 | -------------------------------------------------------------------------------- /src/transition/text.js: -------------------------------------------------------------------------------- 1 | import {tweenValue} from "./tween.js"; 2 | 3 | function textConstant(value) { 4 | return function() { 5 | this.textContent = value; 6 | }; 7 | } 8 | 9 | function textFunction(value) { 10 | return function() { 11 | var value1 = value(this); 12 | this.textContent = value1 == null ? "" : value1; 13 | }; 14 | } 15 | 16 | export default function(value) { 17 | return this.tween("text", typeof value === "function" 18 | ? textFunction(tweenValue(this, "text", value)) 19 | : textConstant(value == null ? "" : value + "")); 20 | } 21 | -------------------------------------------------------------------------------- /src/transition/textTween.js: -------------------------------------------------------------------------------- 1 | function textInterpolate(i) { 2 | return function(t) { 3 | this.textContent = i.call(this, t); 4 | }; 5 | } 6 | 7 | function textTween(value) { 8 | var t0, i0; 9 | function tween() { 10 | var i = value.apply(this, arguments); 11 | if (i !== i0) t0 = (i0 = i) && textInterpolate(i); 12 | return t0; 13 | } 14 | tween._value = value; 15 | return tween; 16 | } 17 | 18 | export default function(value) { 19 | var key = "text"; 20 | if (arguments.length < 1) return (key = this.tween(key)) && key._value; 21 | if (value == null) return this.tween(key, null); 22 | if (typeof value !== "function") throw new Error; 23 | return this.tween(key, textTween(value)); 24 | } 25 | -------------------------------------------------------------------------------- /src/transition/transition.js: -------------------------------------------------------------------------------- 1 | import {Transition, newId} from "./index.js"; 2 | import schedule, {get} from "./schedule.js"; 3 | 4 | export default function() { 5 | var name = this._name, 6 | id0 = this._id, 7 | id1 = newId(); 8 | 9 | for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { 10 | for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { 11 | if (node = group[i]) { 12 | var inherit = get(node, id0); 13 | schedule(node, name, id1, i, group, { 14 | time: inherit.time + inherit.delay + inherit.duration, 15 | delay: 0, 16 | duration: inherit.duration, 17 | ease: inherit.ease 18 | }); 19 | } 20 | } 21 | } 22 | 23 | return new Transition(groups, this._parents, name, id1); 24 | } 25 | -------------------------------------------------------------------------------- /src/transition/tween.js: -------------------------------------------------------------------------------- 1 | import {get, set} from "./schedule.js"; 2 | 3 | function tweenRemove(id, name) { 4 | var tween0, tween1; 5 | return function() { 6 | var schedule = set(this, id), 7 | tween = schedule.tween; 8 | 9 | // If this node shared tween with the previous node, 10 | // just assign the updated shared tween and we’re done! 11 | // Otherwise, copy-on-write. 12 | if (tween !== tween0) { 13 | tween1 = tween0 = tween; 14 | for (var i = 0, n = tween1.length; i < n; ++i) { 15 | if (tween1[i].name === name) { 16 | tween1 = tween1.slice(); 17 | tween1.splice(i, 1); 18 | break; 19 | } 20 | } 21 | } 22 | 23 | schedule.tween = tween1; 24 | }; 25 | } 26 | 27 | function tweenFunction(id, name, value) { 28 | var tween0, tween1; 29 | if (typeof value !== "function") throw new Error; 30 | return function() { 31 | var schedule = set(this, id), 32 | tween = schedule.tween; 33 | 34 | // If this node shared tween with the previous node, 35 | // just assign the updated shared tween and we’re done! 36 | // Otherwise, copy-on-write. 37 | if (tween !== tween0) { 38 | tween1 = (tween0 = tween).slice(); 39 | for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { 40 | if (tween1[i].name === name) { 41 | tween1[i] = t; 42 | break; 43 | } 44 | } 45 | if (i === n) tween1.push(t); 46 | } 47 | 48 | schedule.tween = tween1; 49 | }; 50 | } 51 | 52 | export default function(name, value) { 53 | var id = this._id; 54 | 55 | name += ""; 56 | 57 | if (arguments.length < 2) { 58 | var tween = get(this.node(), id).tween; 59 | for (var i = 0, n = tween.length, t; i < n; ++i) { 60 | if ((t = tween[i]).name === name) { 61 | return t.value; 62 | } 63 | } 64 | return null; 65 | } 66 | 67 | return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); 68 | } 69 | 70 | export function tweenValue(transition, name, value) { 71 | var id = transition._id; 72 | 73 | transition.each(function() { 74 | var schedule = set(this, id); 75 | (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); 76 | }); 77 | 78 | return function(node) { 79 | return get(node, id).value[name]; 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "parserOptions": { 4 | "sourceType": "module", 5 | "ecmaVersion": 8 6 | }, 7 | "env": { 8 | "mocha": true, 9 | "node": true, 10 | "es6": true, 11 | "browser": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/active-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select} from "d3-selection"; 3 | import {timeout} from "d3-timer"; 4 | import {active} from "../src/index.js"; 5 | import it from "./jsdom.js"; 6 | 7 | it("active(node) returns null if the specified node has no active transition with the null name", async () => { 8 | const root = document.documentElement; 9 | const s = select(root); 10 | 11 | // No transitions pending. 12 | assert.strictEqual(active(root), null); 13 | 14 | // Two transitions created. 15 | s.transition().delay(50).duration(50); 16 | s.transition("foo").duration(50); 17 | assert.strictEqual(active(root), null); 18 | 19 | // One transition scheduled; one active with a different name. 20 | await new Promise(resolve => timeout(() => { 21 | assert.strictEqual(active(root), null); 22 | resolve(); 23 | })); 24 | 25 | // No transitions remaining after the transition ends. 26 | await new Promise(resolve => timeout(() => { 27 | assert.strictEqual(active(root), null); 28 | resolve(); 29 | }, 100)); 30 | }); 31 | 32 | it("active(node, null) returns null if the specified node has no active transition with the null name", async () => { 33 | const root = document.documentElement; 34 | const s = select(root); 35 | 36 | // No transitions pending. 37 | assert.strictEqual(active(root, null), null); 38 | 39 | // Two transitions created. 40 | s.transition().delay(50).duration(50); 41 | s.transition("foo").duration(50); 42 | assert.strictEqual(active(root, null), null); 43 | 44 | // One transition scheduled; one active with a different name. 45 | await new Promise(resolve => timeout(() => { 46 | assert.strictEqual(active(root, null), null); 47 | resolve(); 48 | })); 49 | 50 | // No transitions remaining after the transition ends. 51 | await new Promise(resolve => timeout(() => { 52 | assert.strictEqual(active(root, null), null); 53 | resolve(); 54 | }, 100)); 55 | }); 56 | 57 | it("active(node, undefined) returns null if the specified node has no active transition with the null name", async () => { 58 | const root = document.documentElement; 59 | const s = select(root); 60 | 61 | // No transitions pending. 62 | assert.strictEqual(active(root, undefined), null); 63 | 64 | // Two transitions created. 65 | s.transition().delay(50).duration(50); 66 | s.transition("foo").duration(50); 67 | assert.strictEqual(active(root, undefined), null); 68 | 69 | // One transition scheduled; one active with a different name. 70 | await new Promise(resolve => timeout(() => { 71 | assert.strictEqual(active(root, undefined), null); 72 | resolve(); 73 | })); 74 | 75 | // No transitions remaining after the transition ends. 76 | await new Promise(resolve => timeout(() => { 77 | assert.strictEqual(active(root, undefined), null); 78 | resolve(); 79 | }, 100)); 80 | }); 81 | 82 | it("active(node, name) returns null if the specified node has no active transition with the specified name", async () => { 83 | const root = document.documentElement; 84 | const s = select(root); 85 | 86 | // No transitions pending. 87 | assert.strictEqual(active(root, "foo"), null); 88 | 89 | // Two transitions created. 90 | s.transition("foo").delay(50).duration(50); 91 | s.transition().duration(50); 92 | assert.strictEqual(active(root, null), null); 93 | 94 | // One transition scheduled; one active with a different name. 95 | assert.strictEqual(active(root, "foo"), null); 96 | 97 | // One transition scheduled. 98 | await new Promise(resolve => timeout(() => { 99 | assert.strictEqual(active(root, "foo"), null); 100 | resolve(); 101 | })); 102 | 103 | // No transitions remaining after the transition ends. 104 | await new Promise(resolve => timeout(() => { 105 | assert.strictEqual(active(root, "foo"), null); 106 | resolve(); 107 | }, 100)); 108 | }); 109 | 110 | it("active(node) returns the active transition on the specified node with the null name", async () => { 111 | const root = document.documentElement; 112 | const s = select(root); 113 | const t = s.transition().on("start", check).tween("tween", tweened).on("end", check); 114 | 115 | function check() { 116 | const a = active(root); 117 | assert.deepStrictEqual(a._groups, [[root]]); 118 | assert.deepStrictEqual(a._parents, [null]); 119 | assert.strictEqual(a._name, null); 120 | assert.strictEqual(a._id, t._id); 121 | } 122 | 123 | function tweened() { 124 | check(); 125 | return t => { 126 | if (t >= 1) check(); 127 | }; 128 | } 129 | 130 | await t.end(); 131 | }); 132 | 133 | it("active(node, name) returns the active transition on the specified node with the specified name", async () => { 134 | const root = document.documentElement; 135 | const s = select(root); 136 | const t = s.transition("foo").on("start", check).tween("tween", tweened).on("end", check); 137 | 138 | function check() { 139 | const a = active(root, "foo"); 140 | assert.deepStrictEqual(a._groups, [[root]]); 141 | assert.deepStrictEqual(a._parents, [null]); 142 | assert.strictEqual(a._name, "foo"); 143 | assert.strictEqual(a._id, t._id); 144 | } 145 | 146 | function tweened() { 147 | check(); 148 | return t => { 149 | if (t >= 1) check(); 150 | }; 151 | } 152 | 153 | await t.end(); 154 | }); 155 | -------------------------------------------------------------------------------- /test/error-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select} from "d3-selection"; 3 | import {timeout} from "d3-timer"; 4 | import "../src/index.js"; 5 | import it from "./jsdom.js"; 6 | 7 | describe("with an uncaught error", () => { 8 | let listeners; 9 | 10 | beforeEach(() => { 11 | listeners = process.listeners("uncaughtException"); 12 | process.removeAllListeners("uncaughtException"); 13 | process.once("uncaughtException", () => {}); 14 | }); 15 | 16 | afterEach(() => { 17 | for (const listener of listeners) { 18 | process.on("uncaughtException", listener); 19 | } 20 | }); 21 | 22 | it("transition.on(\"start\", error) terminates the transition", async () => { 23 | const root = document.documentElement; 24 | const s = select(root); 25 | s.transition().on("start", () => { throw new Error; }); 26 | await new Promise(resolve => timeout(resolve)); 27 | assert.strictEqual(root.__transition, undefined); 28 | }); 29 | 30 | it("transition.on(\"start\", error) with delay terminates the transition", async () => { 31 | const root = document.documentElement; 32 | const s = select(root); 33 | s.transition().delay(50).on("start", () => { throw new Error; }); 34 | await new Promise(resolve => timeout(resolve, 50)); 35 | assert.strictEqual(root.__transition, undefined); 36 | }); 37 | 38 | it("transition.tween(\"foo\", error) terminates the transition", async () => { 39 | const root = document.documentElement; 40 | const s = select(root); 41 | s.transition().tween("foo", () => { throw new Error; }); 42 | await new Promise(resolve => timeout(resolve)); 43 | assert.strictEqual(root.__transition, undefined); 44 | }); 45 | 46 | it("transition.tween(\"foo\", error) with delay terminates the transition", async () => { 47 | const root = document.documentElement; 48 | const s = select(root); 49 | s.transition().delay(50).tween("foo", () => { throw new Error; }); 50 | await new Promise(resolve => timeout(resolve, 50)); 51 | assert.strictEqual(root.__transition, undefined); 52 | }); 53 | 54 | it("transition.tween(\"foo\", deferredError) terminates the transition", async () => { 55 | const root = document.documentElement; 56 | const s = select(root); 57 | s.transition().duration(50).tween("foo", () => { return function(t) { if (t === 1) throw new Error; }; }); 58 | await new Promise(resolve => timeout(resolve, 50)); 59 | assert.strictEqual(root.__transition, undefined); 60 | }); 61 | 62 | it("transition.on(\"end\", error) terminates the transition", async () => { 63 | const root = document.documentElement; 64 | const s = select(root); 65 | s.transition().delay(50).duration(50).on("end", () => { throw new Error; }); 66 | await new Promise(resolve => timeout(resolve, 100)); 67 | assert.strictEqual(root.__transition, undefined); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /test/interrupt-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select} from "d3-selection"; 3 | import {interrupt} from "../src/index.js"; 4 | import it from "./jsdom.js"; 5 | 6 | it("interrupt(node) cancels any pending transitions on the specified node", () => { 7 | const root = document.documentElement; 8 | const s = select(root); 9 | const t1 = s.transition(); 10 | const t2 = t1.transition(); 11 | assert.strictEqual(t1._id in root.__transition, true); 12 | assert.strictEqual(t2._id in root.__transition, true); 13 | interrupt(root); 14 | assert.strictEqual(root.__transition, undefined); 15 | }); 16 | 17 | it("selection.interrupt(name) only cancels pending transitions with the specified name", () => { 18 | const root = document.documentElement; 19 | const s = select(root); 20 | const t1 = s.transition("foo"); 21 | const t2 = s.transition(); 22 | assert.strictEqual(t1._id in root.__transition, true); 23 | assert.strictEqual(t2._id in root.__transition, true); 24 | interrupt(root, "foo"); 25 | assert.strictEqual(t1._id in root.__transition, false); 26 | assert.strictEqual(t2._id in root.__transition, true); 27 | }); 28 | -------------------------------------------------------------------------------- /test/jsdom.js: -------------------------------------------------------------------------------- 1 | import {JSDOM} from "jsdom"; 2 | 3 | export default function jsdomit(message, html, run) { 4 | if (arguments.length < 3) run = html, html = ""; 5 | return it(message, async () => { 6 | try { 7 | const dom = new JSDOM(html); 8 | global.window = dom.window; 9 | global.document = dom.window.document; 10 | await run(); 11 | } finally { 12 | delete global.window; 13 | delete global.document; 14 | } 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /test/selection/interrupt-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select} from "d3-selection"; 3 | import {timeout} from "d3-timer"; 4 | import "../../src/index.js"; 5 | import {CREATED, ENDED, ENDING, SCHEDULED, STARTED, STARTING} from "../../src/transition/schedule.js"; 6 | import it from "../jsdom.js"; 7 | 8 | it("selection.interrupt() returns the selection", () => { 9 | const s = select(document); 10 | assert.strictEqual(s.interrupt(), s); 11 | }); 12 | 13 | it("selection.interrupt() cancels any pending transitions on the selected elements", () => { 14 | const root = document.documentElement; 15 | const s = select(root); 16 | const t1 = s.transition(); 17 | const t2 = t1.transition(); 18 | assert.strictEqual(t1._id in root.__transition, true); 19 | assert.strictEqual(t2._id in root.__transition, true); 20 | assert.strictEqual(s.interrupt(), s); 21 | assert.strictEqual(root.__transition, undefined); 22 | }); 23 | 24 | it("selection.interrupt() only cancels pending transitions with the null name", () => { 25 | const root = document.documentElement; 26 | const s = select(root); 27 | const t1 = s.transition("foo"); 28 | const t2 = s.transition(); 29 | assert.strictEqual(t1._id in root.__transition, true); 30 | assert.strictEqual(t2._id in root.__transition, true); 31 | assert.strictEqual(s.interrupt(), s); 32 | assert.strictEqual(t1._id in root.__transition, true); 33 | assert.strictEqual(t2._id in root.__transition, false); 34 | }); 35 | 36 | it("selection.interrupt(null) only cancels pending transitions with the null name", () => { 37 | const root = document.documentElement; 38 | const s = select(root); 39 | const t1 = s.transition("foo"); 40 | const t2 = s.transition(); 41 | assert.strictEqual(t1._id in root.__transition, true); 42 | assert.strictEqual(t2._id in root.__transition, true); 43 | assert.strictEqual(s.interrupt(null), s); 44 | assert.strictEqual(t1._id in root.__transition, true); 45 | assert.strictEqual(t2._id in root.__transition, false); 46 | }); 47 | 48 | it("selection.interrupt(undefined) only cancels pending transitions with the null name", () => { 49 | const root = document.documentElement; 50 | const s = select(root); 51 | const t1 = s.transition("foo"); 52 | const t2 = s.transition(); 53 | assert.strictEqual(t1._id in root.__transition, true); 54 | assert.strictEqual(t2._id in root.__transition, true); 55 | assert.strictEqual(s.interrupt(undefined), s); 56 | assert.strictEqual(t1._id in root.__transition, true); 57 | assert.strictEqual(t2._id in root.__transition, false); 58 | }); 59 | 60 | it("selection.interrupt(name) only cancels pending transitions with the specified name", () => { 61 | const root = document.documentElement; 62 | const s = select(root); 63 | const t1 = s.transition("foo"); 64 | const t2 = s.transition(); 65 | assert.strictEqual(t1._id in root.__transition, true); 66 | assert.strictEqual(t2._id in root.__transition, true); 67 | assert.strictEqual(s.interrupt("foo"), s); 68 | assert.strictEqual(t1._id in root.__transition, false); 69 | assert.strictEqual(t2._id in root.__transition, true); 70 | }); 71 | 72 | it("selection.interrupt(name) coerces the name to a string", () => { 73 | const root = document.documentElement; 74 | const s = select(root); 75 | const t1 = s.transition("foo"); 76 | const t2 = s.transition(); 77 | assert.strictEqual(t1._id in root.__transition, true); 78 | assert.strictEqual(t2._id in root.__transition, true); 79 | assert.strictEqual(s.interrupt({toString() { return "foo"; }}), s); 80 | assert.strictEqual(t1._id in root.__transition, false); 81 | assert.strictEqual(t2._id in root.__transition, true); 82 | }); 83 | 84 | it("selection.interrupt() does nothing if there is no transition on the selected elements", () => { 85 | const root = document.documentElement; 86 | const s = select(root); 87 | assert.strictEqual(root.__transition, undefined); 88 | assert.strictEqual(s.interrupt(), s); 89 | assert.strictEqual(root.__transition, undefined); 90 | }); 91 | 92 | it("selection.interrupt() dispatches an interrupt event to the started transition on the selected elements", async () => { 93 | const root = document.documentElement; 94 | let interrupts = 0; 95 | const s = select(root); 96 | const t = s.transition().on("interrupt", () => { ++interrupts; }); 97 | await new Promise(resolve => timeout(() => { 98 | const schedule = root.__transition[t._id]; 99 | assert.strictEqual(schedule.state, STARTED); 100 | s.interrupt(); 101 | assert.strictEqual(schedule.timer._call, null); 102 | assert.strictEqual(schedule.state, ENDED); 103 | assert.strictEqual(root.__transition, undefined); 104 | assert.strictEqual(interrupts, 1); 105 | resolve(); 106 | })); 107 | }); 108 | 109 | it("selection.interrupt() destroys the schedule after dispatching the interrupt event", async () => { 110 | const root = document.documentElement; 111 | const s = select(root); 112 | const t = s.transition().on("interrupt", interrupted); 113 | await new Promise(resolve => timeout(() => { 114 | s.interrupt(); 115 | resolve(); 116 | })); 117 | function interrupted() { 118 | assert.strictEqual(t.delay(), 0); 119 | assert.strictEqual(t.duration(), 250); 120 | assert.strictEqual(t.on("interrupt"), interrupted); 121 | } 122 | }); 123 | 124 | it("selection.interrupt() does not dispatch an interrupt event to a starting transition", async () => { 125 | const root = document.documentElement; 126 | let interrupts = 0; 127 | const s = select(root); 128 | const t = s.transition().on("interrupt", () => { ++interrupts; }); 129 | await new Promise(resolve => t.on("start", () => { 130 | const schedule = root.__transition[t._id]; 131 | assert.strictEqual(schedule.state, STARTING); 132 | s.interrupt(); 133 | assert.strictEqual(schedule.timer._call, null); 134 | assert.strictEqual(schedule.state, ENDED); 135 | assert.strictEqual(root.__transition, undefined); 136 | assert.strictEqual(interrupts, 0); 137 | resolve(); 138 | })); 139 | }); 140 | 141 | it("selection.interrupt() prevents a created transition from starting", async () => { 142 | const root = document.documentElement; 143 | let starts = 0; 144 | const s = select(root); 145 | const t = s.transition().on("start", () => { ++starts; }); 146 | const schedule = root.__transition[t._id]; 147 | assert.strictEqual(schedule.state, CREATED); 148 | s.interrupt(); 149 | assert.strictEqual(schedule.timer._call, null); 150 | assert.strictEqual(schedule.state, ENDED); 151 | assert.strictEqual(root.__transition, undefined); 152 | await new Promise(resolve => timeout(resolve, 10)); 153 | assert.strictEqual(starts, 0); 154 | }); 155 | 156 | it("selection.interrupt() prevents a scheduled transition from starting", async () => { 157 | const root = document.documentElement; 158 | let starts = 0; 159 | const s = select(root); 160 | const t = s.transition().delay(50).on("start", () => { ++starts; }); 161 | const schedule = root.__transition[t._id]; 162 | await new Promise(resolve => timeout(resolve)); 163 | assert.strictEqual(schedule.state, SCHEDULED); 164 | s.interrupt(); 165 | assert.strictEqual(schedule.timer._call, null); 166 | assert.strictEqual(schedule.state, ENDED); 167 | assert.strictEqual(root.__transition, undefined); 168 | await new Promise(resolve => timeout(resolve, 60)); 169 | assert.strictEqual(starts, 0); 170 | }); 171 | 172 | it("selection.interrupt() prevents a starting transition from initializing tweens", async () => { 173 | const root = document.documentElement; 174 | let tweens = 0; 175 | const s = select(root); 176 | const t = s.transition().tween("tween", () => { ++tweens; }); 177 | const schedule = root.__transition[t._id]; 178 | await new Promise(resolve => t.on("start", () => { 179 | assert.strictEqual(schedule.state, STARTING); 180 | s.interrupt(); 181 | assert.strictEqual(schedule.timer._call, null); 182 | assert.strictEqual(schedule.state, ENDED); 183 | assert.strictEqual(root.__transition, undefined); 184 | resolve(); 185 | })); 186 | await new Promise(resolve => timeout(resolve, 10)); 187 | assert.strictEqual(tweens, 0); 188 | }); 189 | 190 | it("selection.interrupt() during tween initialization prevents an active transition from continuing", async () => { 191 | const root = document.documentElement; 192 | let tweens = 0; 193 | const s = select(root); 194 | const t = s.transition().tween("tween", () => { s.interrupt(); return () => { ++tweens; }; }); 195 | const schedule = root.__transition[t._id]; 196 | await new Promise(resolve => timeout(resolve, 10)); 197 | assert.strictEqual(schedule.timer._call, null); 198 | assert.strictEqual(schedule.state, ENDED); 199 | assert.strictEqual(root.__transition, undefined); 200 | assert.strictEqual(tweens, 0); 201 | }); 202 | 203 | it("selection.interrupt() prevents an active transition from continuing", async () => { 204 | const root = document.documentElement; 205 | let interrupted = false; 206 | let tweens = 0; 207 | const s = select(root); 208 | const t = s.transition().tween("tween", () => () => { if (interrupted) ++tweens; }); 209 | const schedule = root.__transition[t._id]; 210 | await new Promise(resolve => timeout(() => { 211 | interrupted = true; 212 | assert.strictEqual(schedule.state, STARTED); 213 | s.interrupt(); 214 | assert.strictEqual(schedule.timer._call, null); 215 | assert.strictEqual(schedule.state, ENDED); 216 | assert.strictEqual(root.__transition, undefined); 217 | resolve(); 218 | }, 10)); 219 | await new Promise(resolve => timeout(resolve, 50)); 220 | assert.strictEqual(tweens, 0); 221 | }); 222 | 223 | it("selection.interrupt() during the final tween invocation prevents the end event from being dispatched", async () => { 224 | const root = document.documentElement; 225 | let ends = 0; 226 | const s = select(root); 227 | const t = s.transition().duration(50).tween("tween", tween).on("end", () => { ++ends; }); 228 | const schedule = root.__transition[t._id]; 229 | function tween() { 230 | return (t) => { 231 | if (t >= 1) { 232 | assert.strictEqual(schedule.state, ENDING); 233 | s.interrupt(); 234 | } 235 | }; 236 | } 237 | await new Promise(resolve => timeout(() => { 238 | assert.strictEqual(schedule.timer._call, null); 239 | assert.strictEqual(schedule.state, ENDED); 240 | assert.strictEqual(root.__transition, undefined); 241 | assert.strictEqual(ends, 0); 242 | resolve(); 243 | }, 60)); 244 | }); 245 | 246 | it("selection.interrupt() has no effect on an ended transition", async () => { 247 | const root = document.documentElement; 248 | const s = select(root); 249 | const t = s.transition().duration(50); 250 | const schedule = root.__transition[t._id]; 251 | await t.end(); 252 | assert.strictEqual(schedule.state, ENDED); 253 | assert.strictEqual(schedule.timer._call, null); 254 | s.interrupt(); 255 | assert.strictEqual(schedule.state, ENDED); 256 | assert.strictEqual(schedule.timer._call, null); 257 | assert.strictEqual(root.__transition, undefined); 258 | }); 259 | 260 | it("selection.interrupt() has no effect on an interrupting transition", async () => { 261 | const root = document.documentElement; 262 | let interrupts = 0; 263 | const s = select(root); 264 | const t = s.transition().duration(50).on("interrupt", interrupted); 265 | const schedule = root.__transition[t._id]; 266 | 267 | function interrupted() { 268 | ++interrupts; 269 | s.interrupt(); 270 | } 271 | 272 | await new Promise(resolve => timeout(() => { 273 | assert.strictEqual(schedule.state, STARTED); 274 | s.interrupt(); 275 | assert.strictEqual(schedule.state, ENDED); 276 | assert.strictEqual(schedule.timer._call, null); 277 | assert.strictEqual(interrupts, 1); 278 | resolve(); 279 | })); 280 | }); 281 | -------------------------------------------------------------------------------- /test/selection/transition-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easeBounce, easeCubic} from "d3-ease"; 3 | import {select, selectAll} from "d3-selection"; 4 | import {now, timeout} from "d3-timer"; 5 | import {transition} from "../../src/index.js"; 6 | import it from "../jsdom.js"; 7 | 8 | it("selection.transition() returns an instanceof transition", () => { 9 | const root = document.documentElement; 10 | const s = select(root); 11 | const t = s.transition(); 12 | assert.strictEqual(t instanceof transition, true); 13 | }); 14 | 15 | it("selection.transition() uses the default timing parameters", () => { 16 | const root = document.documentElement; 17 | const s = select(root); 18 | const t = s.transition(); 19 | const schedule = root.__transition[t._id]; 20 | assert.strictEqual(schedule.time, now()); 21 | assert.strictEqual(schedule.delay, 0); 22 | assert.strictEqual(schedule.duration, 250); 23 | assert.strictEqual(schedule.ease, easeCubic); 24 | }); 25 | 26 | it("selection.transition() assigns a monotonically-increasing id", () => { 27 | const root = document.documentElement; 28 | const s = select(root); 29 | const t1 = s.transition(); 30 | const t2 = s.transition(); 31 | const t3 = s.transition(); 32 | assert(t2._id > t1._id); 33 | assert(t3._id > t2._id); 34 | }); 35 | 36 | it("selection.transition() uses a default name of null", () => { 37 | const root = document.documentElement; 38 | const s = select(root); 39 | const t = s.transition(); 40 | const schedule = root.__transition[t._id]; 41 | assert.strictEqual(schedule.name, null); 42 | }); 43 | 44 | it("selection.transition(null) uses a name of null", () => { 45 | const root = document.documentElement; 46 | const s = select(root); 47 | const t = s.transition(null); 48 | const schedule = root.__transition[t._id]; 49 | assert.strictEqual(schedule.name, null); 50 | }); 51 | 52 | it("selection.transition(undefined) uses a name of null", () => { 53 | const root = document.documentElement; 54 | const s = select(root); 55 | const t = s.transition(undefined); 56 | const schedule = root.__transition[t._id]; 57 | assert.strictEqual(schedule.name, null); 58 | }); 59 | 60 | it("selection.transition(name) uses the specified name", () => { 61 | const root = document.documentElement; 62 | const s = select(root); 63 | const t = s.transition("foo"); 64 | const schedule = root.__transition[t._id]; 65 | assert.strictEqual(schedule.name, "foo"); 66 | }); 67 | 68 | it("selection.transition(name) coerces the name to a string", () => { 69 | const root = document.documentElement; 70 | const s = select(root); 71 | const t = s.transition({toString() { return "foo"; }}); 72 | const schedule = root.__transition[t._id]; 73 | assert.strictEqual(schedule.name, "foo"); 74 | }); 75 | 76 | it("selection.transition(transition) inherits the id, name and timing from the corresponding parent in the specified transition", "

", async () => { 77 | const one = document.querySelector("#one"); 78 | const two = document.querySelector("#two"); 79 | const s = selectAll([one, two]); 80 | const t = s.transition().delay(function(d, i) { return i * 50; }).duration(100).ease(easeBounce); 81 | const schedule1 = one.__transition[t._id]; 82 | const schedule2 = two.__transition[t._id]; 83 | const t1b = select(one.firstChild).transition(t); 84 | const schedule1b = one.firstChild.__transition[t._id]; 85 | assert.strictEqual(t1b._id, t._id); 86 | assert.strictEqual(schedule1b.name, schedule1.name); 87 | assert.strictEqual(schedule1b.delay, schedule1.delay); 88 | assert.strictEqual(schedule1b.duration, schedule1.duration); 89 | assert.strictEqual(schedule1b.ease, schedule1.ease); 90 | assert.strictEqual(schedule1b.time, schedule1.time); 91 | await new Promise(resolve => timeout(resolve, 10)); 92 | const t2b = select(two.firstChild).transition(t); 93 | const schedule2b = two.firstChild.__transition[t._id]; 94 | assert.strictEqual(t2b._id, t._id); 95 | assert.strictEqual(schedule2b.name, schedule2.name); 96 | assert.strictEqual(schedule2b.delay, schedule2.delay); 97 | assert.strictEqual(schedule2b.duration, schedule2.duration); 98 | assert.strictEqual(schedule2b.ease, schedule2.ease); 99 | assert.strictEqual(schedule2b.time, schedule2.time); 100 | }); 101 | 102 | it("selection.transition(transition) reselects the existing transition with the specified transition’s id, if any", () => { 103 | const root = document.documentElement; 104 | const foo = () => {}; 105 | const bar = () => {}; 106 | const s = select(root); 107 | const t1 = s.transition().tween("tween", foo); 108 | const schedule1 = root.__transition[t1._id]; 109 | const t2 = s.transition(t1).tween("tween", bar); 110 | const schedule2 = root.__transition[t2._id]; 111 | assert.strictEqual(t1._id, t2._id); 112 | assert.strictEqual(schedule1, schedule2); 113 | assert.strictEqual(t1.tween("tween"), bar); 114 | assert.strictEqual(t2.tween("tween"), bar); 115 | }); 116 | 117 | it("selection.transition(transition) throws an error if the specified transition is not found", "

", () => { 118 | const one = document.querySelector("#one"); 119 | const two = document.querySelector("#two"); 120 | const t1 = select(one).transition(); 121 | const t2 = select(two).transition().delay(50); 122 | assert.throws(() => select(two).transition(t1), /transition .* not found/); 123 | assert.throws(() => select(one).transition(t2), /transition .* not found/); 124 | }); 125 | -------------------------------------------------------------------------------- /test/transition/attr-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easeCubic} from "d3-ease"; 3 | import {interpolateNumber, interpolateRgb, interpolateString} from "d3-interpolate"; 4 | import {select, selectAll} from "d3-selection"; 5 | import {timeout} from "d3-timer"; 6 | import "../../src/index.js"; 7 | import it from "../jsdom.js"; 8 | 9 | it("transition.attr(name, value) creates an tween to the specified value", async () => { 10 | const root = document.documentElement; 11 | const ease = easeCubic; 12 | const duration = 250; 13 | const interpolate = interpolateRgb("red", "blue"); 14 | const s = select(root).attr("fill", "red"); 15 | s.transition().attr("fill", "blue"); 16 | await new Promise(resolve => timeout(elapsed => { 17 | assert.strictEqual(root.getAttribute("fill"), interpolate(ease(elapsed / duration))); 18 | resolve(); 19 | }, 125)); 20 | }); 21 | 22 | it("transition.attr(name, value) creates a namespaced tween to the specified value", async () => { 23 | const root = document.documentElement; 24 | const ease = easeCubic; 25 | const duration = 250; 26 | const interpolate = interpolateRgb("red", "blue"); 27 | const s = select(root).attr("svg:fill", "red"); 28 | s.transition().attr("svg:fill", "blue"); 29 | await new Promise(resolve => timeout(elapsed => { 30 | assert.strictEqual(root.getAttributeNS("http://www.w3.org/2000/svg", "fill"), interpolate(ease(elapsed / duration))); 31 | resolve(); 32 | }, 125)); 33 | }); 34 | 35 | it("transition.attr(name, value) creates an tween to the value returned by the specified function", async () => { 36 | const root = document.documentElement; 37 | const ease = easeCubic; 38 | const duration = 250; 39 | const interpolate = interpolateRgb("red", "blue"); 40 | const s = select(root).attr("fill", "red"); 41 | s.transition().attr("fill", function() { return "blue"; }); 42 | await new Promise(resolve => timeout(elapsed => { 43 | assert.strictEqual(root.getAttribute("fill"), interpolate(ease(elapsed / duration))); 44 | resolve(); 45 | }, 125)); 46 | }); 47 | 48 | it("transition.attr(name, value) creates a namespaced tween to the value returned by the specified function", async () => { 49 | const root = document.documentElement; 50 | const ease = easeCubic; 51 | const duration = 250; 52 | const interpolate = interpolateRgb("red", "blue"); 53 | const s = select(root).attr("svg:fill", "red"); 54 | s.transition().attr("svg:fill", function() { return "blue"; }); 55 | await new Promise(resolve => timeout(elapsed => { 56 | assert.strictEqual(root.getAttributeNS("http://www.w3.org/2000/svg", "fill"), interpolate(ease(elapsed / duration))); 57 | resolve(); 58 | }, 125)); 59 | }); 60 | 61 | it("transition.attr(name, constant) is a noop if the string-coerced value matches the current value on tween initialization", async () => { 62 | const root = document.documentElement; 63 | const s = select(root).attr("foo", 1); 64 | s.transition().attr("foo", 1); 65 | timeout(() => root.setAttribute("foo", 2), 125); 66 | await new Promise(resolve => timeout(() => { 67 | assert.strictEqual(root.getAttribute("foo"), "2"); 68 | resolve(); 69 | }, 250)); 70 | }); 71 | 72 | it("transition.attr(ns:name, constant) is a noop if the string-coerced value matches the current value on tween initialization", async () => { 73 | const root = document.documentElement; 74 | const s = select(root).attr("svg:foo", 1); 75 | s.transition().attr("svg:foo", 1); 76 | timeout(() => root.setAttributeNS("http://www.w3.org/2000/svg", "foo", 2), 125); 77 | await new Promise(resolve => timeout(() => { 78 | assert.strictEqual(root.getAttributeNS("http://www.w3.org/2000/svg", "foo"), "2"); 79 | resolve(); 80 | }, 250)); 81 | }); 82 | 83 | it("transition.attr(name, function) is a noop if the string-coerced value matches the current value on tween initialization", async () => { 84 | const root = document.documentElement; 85 | const s = select(root).attr("foo", 1); 86 | s.transition().attr("foo", function() { return 1; }); 87 | timeout(() => root.setAttribute("foo", 2), 125); 88 | await new Promise(resolve => timeout(() => { 89 | assert.strictEqual(root.getAttribute("foo"), "2"); 90 | resolve(); 91 | }, 250)); 92 | }); 93 | 94 | it("transition.attr(ns:name, function) is a noop if the string-coerced value matches the current value on tween initialization", async () => { 95 | const root = document.documentElement; 96 | const s = select(root).attr("svg:foo", 1); 97 | s.transition().attr("svg:foo", function() { return 1; }); 98 | timeout(() => root.setAttributeNS("http://www.w3.org/2000/svg", "foo", 2), 125); 99 | await new Promise(resolve => timeout(() => { 100 | assert.strictEqual(root.getAttributeNS("http://www.w3.org/2000/svg", "foo"), "2"); 101 | resolve(); 102 | }, 250)); 103 | }); 104 | 105 | it("transition.attr(name, constant) uses interpolateNumber if value is a number", async () => { 106 | const root = document.documentElement; 107 | const s = select(root).attr("foo", "15px"); 108 | s.transition().attr("foo", 10); 109 | await new Promise(resolve => timeout(() => { 110 | assert.strictEqual(root.getAttribute("foo"), "NaN"); 111 | resolve(); 112 | }, 125)); 113 | }); 114 | 115 | it("transition.attr(name, function) uses interpolateNumber if value is a number", async () => { 116 | const root = document.documentElement; 117 | const s = select(root).attr("foo", "15px"); 118 | s.transition().attr("foo", () => 10); 119 | await new Promise(resolve => timeout(() => { 120 | assert.strictEqual(root.getAttribute("foo"), "NaN"); 121 | resolve(); 122 | }, 125)); 123 | }); 124 | 125 | it("transition.attr(name, value) immediately evaluates the specified function with the expected context and arguments", "

", async () => { 126 | const one = document.querySelector("#one"); 127 | const two = document.querySelector("#two"); 128 | const ease = easeCubic; 129 | const duration = 250; 130 | const interpolate1 = interpolateRgb("cyan", "red"); 131 | const interpolate2 = interpolateRgb("magenta", "green"); 132 | const s = selectAll([one, two]).data(["red", "green"]); 133 | const result = []; 134 | s.transition().attr("fill", function(d, i, nodes) { result.push([d, i, nodes, this]); return d; }); 135 | assert.deepStrictEqual(result, [ 136 | ["red", 0, [one, two], one], 137 | ["green", 1, [one, two], two] 138 | ]); 139 | await new Promise(resolve => timeout(elapsed => { 140 | assert.strictEqual(one.getAttribute("fill"), interpolate1(ease(elapsed / duration))); 141 | assert.strictEqual(two.getAttribute("fill"), interpolate2(ease(elapsed / duration))); 142 | resolve(); 143 | }, 125)); 144 | }); 145 | 146 | it("transition.attr(name, value) constructs an interpolator using the current value on start", async () => { 147 | const root = document.documentElement; 148 | const ease = easeCubic; 149 | const duration = 250; 150 | const interpolate = interpolateRgb("red", "blue"); 151 | const s = select(root); 152 | s.transition().on("start", function() { s.attr("fill", "red"); }).attr("fill", function() { return "blue"; }); 153 | await new Promise(resolve => timeout(elapsed => { 154 | assert.strictEqual(root.getAttribute("fill"), interpolate(ease(elapsed / duration))); 155 | resolve(); 156 | }, 125)); 157 | }); 158 | 159 | it("transition.attr(name, null) creates an tween which removes the specified attribute post-start", async () => { 160 | const root = document.documentElement; 161 | const s = select(root).attr("fill", "red"); 162 | const started = () => assert.strictEqual(root.getAttribute("fill"), "red"); 163 | s.transition().attr("fill", null).on("start", started); 164 | await new Promise(resolve => timeout(() => { 165 | assert.strictEqual(root.hasAttribute("fill"), false); 166 | resolve(); 167 | })); 168 | }); 169 | 170 | it("transition.attr(name, null) creates an tween which removes the specified namespaced attribute post-start", async () => { 171 | const root = document.documentElement; 172 | const s = select(root).attr("svg:fill", "red"); 173 | const started = () => assert.strictEqual(root.getAttributeNS("http://www.w3.org/2000/svg", "fill"), "red"); 174 | s.transition().attr("svg:fill", null).on("start", started); 175 | await new Promise(resolve => timeout(() => { 176 | assert.strictEqual(root.hasAttributeNS("http://www.w3.org/2000/svg", "fill"), false); 177 | resolve(); 178 | })); 179 | }); 180 | 181 | it("transition.attr(name, value) creates an tween which removes the specified attribute post-start if the specified function returns null", async () => { 182 | const root = document.documentElement; 183 | const s = select(root).attr("fill", "red"); 184 | const started = () => assert.strictEqual(root.getAttribute("fill"), "red"); 185 | s.transition().attr("fill", function() {}).on("start", started); 186 | await new Promise(resolve => timeout(() => { 187 | assert.strictEqual(root.hasAttribute("fill"), false); 188 | resolve(); 189 | })); 190 | }); 191 | 192 | it("transition.attr(name, value) creates an tween which removes the specified namespaced attribute post-start if the specified function returns null", async () => { 193 | const root = document.documentElement; 194 | const s = select(root).attr("svg:fill", "red"); 195 | const started = () => assert.strictEqual(root.getAttributeNS("http://www.w3.org/2000/svg", "fill"), "red"); 196 | s.transition().attr("svg:fill", function() {}).on("start", started); 197 | await new Promise(resolve => timeout(() => { 198 | assert.strictEqual(root.hasAttributeNS("http://www.w3.org/2000/svg", "fill"), false); 199 | resolve(); 200 | })); 201 | }); 202 | 203 | it("transition.attr(name, value) interpolates numbers", async () => { 204 | const root = document.documentElement; 205 | const ease = easeCubic; 206 | const duration = 250; 207 | const interpolate = interpolateNumber(1, 2); 208 | const s = select(root).attr("foo", 1); 209 | s.transition().attr("foo", 2); 210 | await new Promise(resolve => timeout(elapsed => { 211 | assert.strictEqual(root.getAttribute("foo"), interpolate(ease(elapsed / duration)) + ""); 212 | resolve(); 213 | }, 125)); 214 | }); 215 | 216 | it("transition.attr(name, value) interpolates strings", async () => { 217 | const root = document.documentElement; 218 | const ease = easeCubic; 219 | const duration = 250; 220 | const interpolate = interpolateString("1px", "2px"); 221 | const s = select(root).attr("foo", "1px"); 222 | s.transition().attr("foo", "2px"); 223 | await new Promise(resolve => timeout(elapsed => { 224 | assert.strictEqual(root.getAttribute("foo"), interpolate(ease(elapsed / duration))); 225 | resolve(); 226 | }, 125)); 227 | }); 228 | 229 | it("transition.attr(name, value) interpolates colors", async () => { 230 | const root = document.documentElement; 231 | const ease = easeCubic; 232 | const duration = 250; 233 | const interpolate = interpolateRgb("#f00", "#00f"); 234 | const s = select(root).attr("foo", "#f00"); 235 | s.transition().attr("foo", "#00f"); 236 | await new Promise(resolve => timeout(elapsed => { 237 | assert.strictEqual(root.getAttribute("foo"), interpolate(ease(elapsed / duration))); 238 | resolve(); 239 | }, 125)); 240 | }); 241 | 242 | it("transition.attr(name, value) creates an attrTween with the specified name", async () => { 243 | const root = document.documentElement; 244 | const s = select(root).attr("fill", "red"); 245 | const t = s.transition().attr("fill", "blue"); 246 | assert.strictEqual(t.attrTween("fill").call(root).call(root, 0.5), "rgb(128, 0, 128)"); 247 | }); 248 | 249 | it("transition.attr(name, value) creates a tween with the name \"attr.name\"", async () => { 250 | const root = document.documentElement; 251 | const s = select(root).attr("fill", "red"); 252 | const t = s.transition().attr("fill", "blue"); 253 | t.tween("attr.fill").call(root).call(root, 0.5); 254 | assert.strictEqual(root.getAttribute("fill"), "rgb(128, 0, 128)"); 255 | }); 256 | -------------------------------------------------------------------------------- /test/transition/attrTween-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easeCubic} from "d3-ease"; 3 | import {interpolateHcl} from "d3-interpolate"; 4 | import {select, selectAll} from "d3-selection"; 5 | import {timeout, now} from "d3-timer"; 6 | import "../../src/index.js"; 7 | import {ENDING} from "../../src/transition/schedule.js"; 8 | import it from "../jsdom.js"; 9 | 10 | it("transition.attrTween(name, value) defines an attribute tween using the interpolator returned by the specified function", async () => { 11 | const root = document.documentElement; 12 | const interpolate = interpolateHcl("red", "blue"); 13 | select(root).transition().attrTween("foo", () => interpolate); 14 | await new Promise(resolve => timeout(elapsed => { 15 | assert.strictEqual(root.getAttribute("foo"), interpolate(easeCubic(elapsed / 250))); 16 | resolve(); 17 | }, 125)); 18 | }); 19 | 20 | it("transition.attrTween(name, value) invokes the value function with the expected context and arguments", "

", async () => { 21 | const one = document.querySelector("#one"); 22 | const two = document.querySelector("#two"); 23 | const result = []; 24 | selectAll([one, two]).data(["one", "two"]).transition().attrTween("foo", function(d, i, nodes) { result.push([d, i, nodes, this]); }); 25 | await new Promise(resolve => timeout(resolve)); 26 | assert.deepStrictEqual(result, [ 27 | ["one", 0, [one, two], one], 28 | ["two", 1, [one, two], two] 29 | ]); 30 | }); 31 | 32 | it("transition.attrTween(name, value) passes the eased time to the interpolator", async () => { 33 | const root = document.documentElement; 34 | const then = now(); 35 | const duration = 250; 36 | const ease = easeCubic; 37 | const t = select(root).transition().attrTween("foo", () => interpolate); 38 | const schedule = root.__transition[t._id]; 39 | function interpolate(t) { 40 | assert.strictEqual(this, root); 41 | assert.strictEqual(t, schedule.state === ENDING ? 1 : ease((now() - then) / duration)); 42 | } 43 | await t.end(); 44 | }); 45 | 46 | it("transition.attrTween(name, value) allows the specified function to return null for a noop", async () => { 47 | const root = document.documentElement; 48 | const s = select(root).attr("foo", "42").attr("svg:bar", "43"); 49 | s.transition().attrTween("foo", () => {}).attrTween("svg:bar", () => {}); 50 | await new Promise(resolve => timeout(resolve, 125)); 51 | assert.strictEqual(root.getAttribute("foo"), "42"); 52 | assert.strictEqual(root.getAttributeNS("http://www.w3.org/2000/svg", "bar"), "43"); 53 | }); 54 | 55 | it("transition.attrTween(name, value) defines a namespaced attribute tween using the interpolator returned by the specified function", async () => { 56 | const root = document.documentElement; 57 | const interpolate = interpolateHcl("red", "blue"); 58 | select(root).transition().attrTween("svg:foo", () => interpolate); 59 | await new Promise(resolve => timeout(elapsed => { 60 | assert.strictEqual(root.getAttributeNS("http://www.w3.org/2000/svg", "foo"), interpolate(easeCubic(elapsed / 250))); 61 | resolve(); 62 | }, 125)); 63 | }); 64 | 65 | it("transition.attrTween(name, value) coerces the specified name to a string", async () => { 66 | const root = document.documentElement; 67 | const interpolate = interpolateHcl("red", "blue"); 68 | select(root).transition().attrTween({toString() { return "foo"; }}, () => interpolate); 69 | await new Promise(resolve => timeout(elapsed => { 70 | assert.strictEqual(root.getAttribute("foo"), interpolate(easeCubic(elapsed / 250))); 71 | resolve(); 72 | }, 125)); 73 | }); 74 | 75 | it("transition.attrTween(name, value) throws an error if value is not null and not a function", async () => { 76 | const root = document.documentElement; 77 | const t = select(root).transition(); 78 | assert.throws(() => { t.attrTween("foo", 42); }); 79 | }); 80 | 81 | it("transition.attrTween(name, null) removes the specified attribute tween", async () => { 82 | const root = document.documentElement; 83 | const interpolate = interpolateHcl("red", "blue"); 84 | const t = select(root).transition().attrTween("foo", () => interpolate).attrTween("foo", null); 85 | assert.strictEqual(t.attrTween("foo"), null); 86 | assert.strictEqual(t.tween("attr.foo"), null); 87 | await new Promise(resolve => timeout(resolve, 125)); 88 | assert.strictEqual(root.hasAttribute("foo"), false); 89 | }); 90 | 91 | it("transition.attrTween(name) returns the attribute tween with the specified name", async () => { 92 | const root = document.documentElement; 93 | const interpolate = interpolateHcl("red", "blue"); 94 | const tween = () => interpolate; 95 | const started = () => assert.strictEqual(t.attrTween("foo"), tween); 96 | const ended = () => assert.strictEqual(t.attrTween("foo"), tween); 97 | const t = select(root).transition().attrTween("foo", tween).on("start", started).on("end", ended); 98 | assert.strictEqual(t.attrTween("foo"), tween); 99 | assert.strictEqual(t.attrTween("bar"), null); 100 | await t.end(); 101 | }); 102 | 103 | it("transition.attrTween(name) coerces the specified name to a string", async () => { 104 | const root = document.documentElement; 105 | const tween = () => {}; 106 | const t = select(root).transition().attrTween("color", tween); 107 | assert.strictEqual(t.attrTween({toString() { return "color"; }}), tween); 108 | }); 109 | -------------------------------------------------------------------------------- /test/transition/call-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selection} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.call is the same as selection.call", () => { 7 | assert.strictEqual(transition.prototype.call, selection.prototype.call); 8 | }); 9 | -------------------------------------------------------------------------------- /test/transition/delay-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select, selectAll} from "d3-selection"; 3 | import it from "../jsdom.js"; 4 | import "../../src/index.js"; 5 | 6 | it("transition.delay() returns the delay for the first non-null node", "

", () => { 7 | const one = document.querySelector("#one"); 8 | const two = document.querySelector("#two"); 9 | const t1 = select(one).transition(); 10 | const t2 = select(two).transition().delay(50); 11 | assert.strictEqual(one.__transition[t1._id].delay, 0); 12 | assert.strictEqual(two.__transition[t2._id].delay, 50); 13 | assert.strictEqual(t1.delay(), 0); 14 | assert.strictEqual(t2.delay(), 50); 15 | assert.strictEqual(select(one).transition(t1).delay(), 0); 16 | assert.strictEqual(select(two).transition(t2).delay(), 50); 17 | assert.strictEqual(selectAll([null, one]).transition(t1).delay(), 0); 18 | assert.strictEqual(selectAll([null, two]).transition(t2).delay(), 50); 19 | }); 20 | 21 | it("transition.delay(number) sets the delay for each selected element to the specified number", "

", () => { 22 | const one = document.querySelector("#one"); 23 | const two = document.querySelector("#two"); 24 | const t = selectAll([one, two]).transition().delay(50); 25 | assert.strictEqual(one.__transition[t._id].delay, 50); 26 | assert.strictEqual(two.__transition[t._id].delay, 50); 27 | }); 28 | 29 | it("transition.delay(value) coerces the specified value to a number", "

", () => { 30 | const one = document.querySelector("#one"); 31 | const two = document.querySelector("#two"); 32 | const t = selectAll([one, two]).transition().delay("50"); 33 | assert.strictEqual(one.__transition[t._id].delay, 50); 34 | assert.strictEqual(two.__transition[t._id].delay, 50); 35 | }); 36 | 37 | it("transition.delay(function) passes the expected arguments and context to the function", "

", () => { 38 | const one = document.querySelector("#one"); 39 | const two = document.querySelector("#two"); 40 | const result = []; 41 | const s = selectAll([one, two]).data(["one", "two"]); 42 | const t = s.transition().delay(function(d, i, nodes) { result.push([d, i, nodes, this]); }); 43 | assert.deepStrictEqual(result, [ 44 | ["one", 0, t._groups[0], one], 45 | ["two", 1, t._groups[0], two] 46 | ]); 47 | }); 48 | 49 | it("transition.delay(function) sets the delay for each selected element to the number returned by the specified function", "

", () => { 50 | const one = document.querySelector("#one"); 51 | const two = document.querySelector("#two"); 52 | const t = selectAll([one, two]).transition().delay(function(d, i) { return i * 20; }); 53 | assert.strictEqual(one.__transition[t._id].delay, 0); 54 | assert.strictEqual(two.__transition[t._id].delay, 20); 55 | }); 56 | 57 | it("transition.delay(function) coerces the value returned by the specified function to a number", "

", () => { 58 | const one = document.querySelector("#one"); 59 | const two = document.querySelector("#two"); 60 | const t = selectAll([one, two]).transition().delay(function(d, i) { return i * 20 + ""; }); 61 | assert.strictEqual(one.__transition[t._id].delay, 0); 62 | assert.strictEqual(two.__transition[t._id].delay, 20); 63 | }); 64 | -------------------------------------------------------------------------------- /test/transition/duration-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select, selectAll} from "d3-selection"; 3 | import "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.duration() returns the duration for the first non-null node", "

", () => { 7 | const one = document.querySelector("#one"); 8 | const two = document.querySelector("#two"); 9 | const t1 = select(one).transition(); 10 | const t2 = select(two).transition().duration(50); 11 | assert.strictEqual(one.__transition[t1._id].duration, 250); 12 | assert.strictEqual(two.__transition[t2._id].duration, 50); 13 | assert.strictEqual(t1.duration(), 250); 14 | assert.strictEqual(t2.duration(), 50); 15 | assert.strictEqual(select(one).transition(t1).duration(), 250); 16 | assert.strictEqual(select(two).transition(t2).duration(), 50); 17 | assert.strictEqual(selectAll([null, one]).transition(t1).duration(), 250); 18 | assert.strictEqual(selectAll([null, two]).transition(t2).duration(), 50); 19 | }); 20 | 21 | it("transition.duration(number) sets the duration for each selected element to the specified number", "

", () => { 22 | const one = document.querySelector("#one"); 23 | const two = document.querySelector("#two"); 24 | const t = selectAll([one, two]).transition().duration(50); 25 | assert.strictEqual(one.__transition[t._id].duration, 50); 26 | assert.strictEqual(two.__transition[t._id].duration, 50); 27 | }); 28 | 29 | it("transition.duration(value) coerces the specified value to a number", "

", () => { 30 | const one = document.querySelector("#one"); 31 | const two = document.querySelector("#two"); 32 | const t = selectAll([one, two]).transition().duration("50"); 33 | assert.strictEqual(one.__transition[t._id].duration, 50); 34 | assert.strictEqual(two.__transition[t._id].duration, 50); 35 | }); 36 | 37 | it("transition.duration(function) passes the expected arguments and context to the function", "

", () => { 38 | const one = document.querySelector("#one"); 39 | const two = document.querySelector("#two"); 40 | const result = []; 41 | const s = selectAll([one, two]).data(["one", "two"]); 42 | const t = s.transition().duration(function(d, i, nodes) { result.push([d, i, nodes, this]); }); 43 | assert.deepStrictEqual(result, [ 44 | ["one", 0, t._groups[0], one], 45 | ["two", 1, t._groups[0], two] 46 | ]); 47 | }); 48 | 49 | it("transition.duration(function) sets the duration for each selected element to the number returned by the specified function", "

", () => { 50 | const one = document.querySelector("#one"); 51 | const two = document.querySelector("#two"); 52 | const t = selectAll([one, two]).transition().duration(function(d, i) { return i * 20; }); 53 | assert.strictEqual(one.__transition[t._id].duration, 0); 54 | assert.strictEqual(two.__transition[t._id].duration, 20); 55 | }); 56 | 57 | it("transition.duration(function) coerces the value returned by the specified function to a number", "

", () => { 58 | const one = document.querySelector("#one"); 59 | const two = document.querySelector("#two"); 60 | const t = selectAll([one, two]).transition().duration(function(d, i) { return i * 20 + ""; }); 61 | assert.strictEqual(one.__transition[t._id].duration, 0); 62 | assert.strictEqual(two.__transition[t._id].duration, 20); 63 | }); 64 | -------------------------------------------------------------------------------- /test/transition/each-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select, selectAll, selection} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.each is the same as selection.each", () => { 7 | assert.strictEqual(transition.prototype.each, selection.prototype.each); 8 | }); 9 | 10 | it("transition.each() runs as expected", () => { 11 | const root = document.documentElement; 12 | let a = 0; 13 | select(root).transition().each(() => { ++a; }); 14 | assert.strictEqual(a, 1); 15 | a = 0; 16 | selectAll([null, root]).transition().each(() => { ++a; }); 17 | assert.strictEqual(a, 1); 18 | }); 19 | -------------------------------------------------------------------------------- /test/transition/ease-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easeBounce, easeCubic} from "d3-ease"; 3 | import {select, selectAll} from "d3-selection"; 4 | import {timeout} from "d3-timer"; 5 | import "../../src/index.js"; 6 | import {ENDING, RUNNING} from "../../src/transition/schedule.js"; 7 | import it from "../jsdom.js"; 8 | 9 | it("transition.ease() returns the easing function for the first non-null node", "

", () => { 10 | const one = document.querySelector("#one"); 11 | const two = document.querySelector("#two"); 12 | const t1 = select(one).transition(); 13 | const t2 = select(two).transition().ease(easeBounce); 14 | assert.strictEqual(one.__transition[t1._id].ease, easeCubic); 15 | assert.strictEqual(two.__transition[t2._id].ease, easeBounce); 16 | assert.strictEqual(t1.ease(), easeCubic); 17 | assert.strictEqual(t2.ease(), easeBounce); 18 | assert.strictEqual(select(one).transition(t1).ease(), easeCubic); 19 | assert.strictEqual(select(two).transition(t2).ease(), easeBounce); 20 | assert.strictEqual(selectAll([null, one]).transition(t1).ease(), easeCubic); 21 | assert.strictEqual(selectAll([null, two]).transition(t2).ease(), easeBounce); 22 | }); 23 | 24 | it("transition.ease(ease) throws an error if ease is not a function", () => { 25 | const root = document.documentElement; 26 | const t = select(root).transition(); 27 | assert.throws(() => { t.ease(42); }); 28 | assert.throws(() => { t.ease(null); }); 29 | }); 30 | 31 | it("transition.ease(ease) sets the easing function for each selected element to the specified function", "

", () => { 32 | const one = document.querySelector("#one"); 33 | const two = document.querySelector("#two"); 34 | const t = selectAll([one, two]).transition().ease(easeBounce); 35 | assert.strictEqual(one.__transition[t._id].ease, easeBounce); 36 | assert.strictEqual(two.__transition[t._id].ease, easeBounce); 37 | }); 38 | 39 | it("transition.ease(ease) passes the easing function the normalized time in [0, 1]", async () => { 40 | let actual; 41 | const root = document.documentElement; 42 | const ease = t => { actual = t; return t; }; 43 | 44 | select(root).transition().ease(ease); 45 | 46 | await new Promise(resolve => timeout((elapsed) => { 47 | assert.strictEqual(actual, elapsed / 250); 48 | resolve() 49 | }, 100)); 50 | }); 51 | 52 | it("transition.ease(ease) does not invoke the easing function on the last frame", async () => { 53 | const root = document.documentElement; 54 | const ease = t => { assert.strictEqual(schedule.state, RUNNING); return t; }; 55 | const t = select(root).transition().ease(ease); 56 | const schedule = root.__transition[t._id]; 57 | await t.end(); 58 | }); 59 | 60 | it("transition.ease(ease) observes the eased time returned by the easing function", async () => { 61 | const root = document.documentElement; 62 | let expected; 63 | const ease = () => { return expected = Math.random() * 2 - 0.5; }; 64 | const tween = () => { return t => { assert.strictEqual(t, schedule.state === ENDING ? 1 : expected); }; }; 65 | const t = select(root).transition().ease(ease).tween("tween", tween); 66 | const schedule = root.__transition[t._id]; 67 | await t.end(); 68 | }); 69 | -------------------------------------------------------------------------------- /test/transition/easeVarying-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easePolyIn} from "d3-ease"; 3 | import {select} from "d3-selection"; 4 | import "../../src/index.js"; 5 | import it from "../jsdom.js"; 6 | 7 | it("transition.easeVarying(factory) accepts an easing function factory", "

", () => { 8 | const t = select(document).selectAll("h1").data([{exponent: 3}, {exponent: 4}]).transition(); 9 | t.easeVarying(d => easePolyIn.exponent(d.exponent)); 10 | assert.strictEqual(t.ease()(0.5), easePolyIn.exponent(3)(0.5)); 11 | }); 12 | 13 | it("transition.easeVarying(factory) passes factory datum, index, group with the node as this", "

", () => { 14 | const t = select(document).selectAll("h1").data([{exponent: 3}, {exponent: 4}]).transition(); 15 | const results = []; 16 | t.easeVarying(function(d, i, e) { results.push([d, i, e, this]); return t => t; }); 17 | assert.deepStrictEqual(results, [ 18 | [{exponent: 3}, 0, [...t], document.querySelector("#one")], 19 | [{exponent: 4}, 1, [...t], document.querySelector("#two")], 20 | ]); 21 | }); 22 | 23 | it("transition.easeVarying() throws an error if the argument is not a function", "

", () => { 24 | const t = select(document).selectAll("h1").data([{exponent: 3}, {exponent: 4}]).transition(); 25 | assert.throws(() => { t.easeVarying(); }); 26 | assert.throws(() => { t.easeVarying("a"); }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/transition/empty-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selection} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | 5 | it("transition.empty is the same as selection.empty", () => { 6 | assert.strictEqual(transition.prototype.empty, selection.prototype.empty); 7 | }); 8 | -------------------------------------------------------------------------------- /test/transition/filter-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selectAll} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.filter(selector) retains the elements matching the specified selector", "

", () => { 7 | const one = document.querySelector("#one"); 8 | const two = document.querySelector("#two"); 9 | const t1 = selectAll([one, two]).data([1, 2]).transition().delay(function(d) { return d * 10; }); 10 | const t2 = t1.filter("#two"); 11 | assert.strictEqual(t2 instanceof transition, true); 12 | assert.deepStrictEqual(t2._groups, [[two]]); 13 | assert.strictEqual(t2._parents, t1._parents); 14 | assert.strictEqual(t2._name, t1._name); 15 | assert.strictEqual(t2._id, t1._id); 16 | }); 17 | 18 | it("transition.filter(function) retains the elements for which the specified function returns true", "

", () => { 19 | const one = document.querySelector("#one"); 20 | const two = document.querySelector("#two"); 21 | const t1 = selectAll([one, two]).data([1, 2]).transition().delay(function(d) { return d * 10; }); 22 | const t2 = t1.filter(function() { return this === two; }); 23 | assert.strictEqual(t2 instanceof transition, true); 24 | assert.deepStrictEqual(t2._groups, [[two]]); 25 | assert.strictEqual(t2._parents, t1._parents); 26 | assert.strictEqual(t2._name, t1._name); 27 | assert.strictEqual(t2._id, t1._id); 28 | }); 29 | -------------------------------------------------------------------------------- /test/transition/index-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {transition} from "../../src/index.js"; 3 | import it from "../jsdom.js"; 4 | 5 | it("transition() returns a transition on the document element with the null name", () => { 6 | const root = document.documentElement; 7 | const t = transition(); 8 | const schedule = root.__transition[t._id]; 9 | assert.strictEqual(t.node(), root); 10 | assert.strictEqual(schedule.name, null); 11 | }); 12 | 13 | it("transition(null) returns a transition on the document element with the null name", () => { 14 | const root = document.documentElement; 15 | const t = transition(null); 16 | const schedule = root.__transition[t._id]; 17 | assert.strictEqual(t.node(), root); 18 | assert.strictEqual(schedule.name, null); 19 | }); 20 | 21 | it("transition(undefined) returns a transition on the document element with the null name", () => { 22 | const root = document.documentElement; 23 | const t = transition(undefined); 24 | const schedule = root.__transition[t._id]; 25 | assert.strictEqual(t.node(), root); 26 | assert.strictEqual(schedule.name, null); 27 | }); 28 | 29 | it("transition(name) returns a transition on the document element with the specified name", () => { 30 | const root = document.documentElement; 31 | const t = transition("foo"); 32 | const schedule = root.__transition[t._id]; 33 | assert.strictEqual(t.node(), root); 34 | assert.strictEqual(schedule.name, "foo"); 35 | }); 36 | 37 | it("transition.prototype can be extended", () => { 38 | try { 39 | let pass = 0; 40 | transition.prototype.test = () => { return ++pass; }; 41 | assert.strictEqual(transition().test(), 1); 42 | assert.strictEqual(pass, 1); 43 | } finally { 44 | delete transition.prototype.test; 45 | } 46 | }); 47 | 48 | it("transitions are instanceof transition", () => { 49 | assert.strictEqual(transition() instanceof transition, true); 50 | }); 51 | -------------------------------------------------------------------------------- /test/transition/merge-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select, selectAll} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.merge(other) merges elements from the specified other transition for null elements in this transition", "

", () => { 7 | const one = document.querySelector("#one"); 8 | const two = document.querySelector("#two"); 9 | const t0 = select(document.documentElement).transition(); 10 | const t1 = selectAll([null, two]).transition(t0); 11 | const t2 = selectAll([one, null]).transition(t0); 12 | const t3 = t1.merge(t2); 13 | assert.strictEqual(t3 instanceof transition, true); 14 | assert.deepStrictEqual(t3._groups, [[one, two]]); 15 | assert.strictEqual(t3._parents, t1._parents); 16 | assert.strictEqual(t3._name, t1._name); 17 | assert.strictEqual(t3._id, t1._id); 18 | }); 19 | 20 | it("transition.merge(other) throws an error if the other transition has a different id", "

", () => { 21 | const one = document.querySelector("#one"); 22 | const two = document.querySelector("#two"); 23 | const t1 = selectAll([null, two]).transition(); 24 | const t2 = selectAll([one, null]).transition(); 25 | assert.throws(() => { t1.merge(t2); }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/transition/node-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selection} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.node is the same as selection.node", () => { 7 | assert.strictEqual(transition.prototype.node, selection.prototype.node); 8 | }); 9 | -------------------------------------------------------------------------------- /test/transition/nodes-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selection} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.nodes is the same as selection.nodes", () => { 7 | assert.strictEqual(transition.prototype.nodes, selection.prototype.nodes); 8 | }); 9 | -------------------------------------------------------------------------------- /test/transition/on-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select, selectAll} from "d3-selection"; 3 | import {timeout} from "d3-timer"; 4 | import "../../src/index.js"; 5 | import {ENDED, ENDING, STARTING} from "../../src/transition/schedule.js"; 6 | import it from "../jsdom.js"; 7 | 8 | it("transition.on(type, listener) throws an error if listener is not a function", async () => { 9 | const root = document.documentElement; 10 | const t = select(root).transition(); 11 | assert.throws(() => { t.on("start", 42); }); 12 | }); 13 | 14 | it("transition.on(typename) returns the listener with the specified typename, if any", async () => { 15 | const root = document.documentElement; 16 | const foo = () => {}; 17 | const bar = () => {}; 18 | const t = select(root).transition().on("start", foo).on("start.bar", bar); 19 | assert.strictEqual(t.on("start"), foo); 20 | assert.strictEqual(t.on("start.foo"), undefined); 21 | assert.strictEqual(t.on("start.bar"), bar); 22 | assert.strictEqual(t.on("end"), undefined); 23 | }); 24 | 25 | it("transition.on(typename) throws an error if the specified type is not supported", async () => { 26 | const root = document.documentElement; 27 | const t = select(root).transition(); 28 | assert.throws(() => { t.on("foo"); }); 29 | }); 30 | 31 | it("transition.on(typename, listener) throws an error if the specified type is not supported", async () => { 32 | const root = document.documentElement; 33 | const t = select(root).transition(); 34 | assert.throws(() => { t.on("foo", () => {}); }); 35 | }); 36 | 37 | it("transition.on(typename, listener) throws an error if the specified listener is not a function", async () => { 38 | const root = document.documentElement; 39 | const t = select(root).transition(); 40 | assert.throws(() => { t.on("foo", 42); }); 41 | }); 42 | 43 | it("transition.on(typename, null) removes the listener with the specified typename, if any", async () => { 44 | const root = document.documentElement; 45 | let starts = 0; 46 | const t = select(root).transition().on("start.foo", () => { ++starts; }); 47 | const schedule = root.__transition[t._id]; 48 | assert.strictEqual(t.on("start.foo", null), t); 49 | assert.strictEqual(t.on("start.foo"), undefined); 50 | assert.strictEqual(schedule.on.on("start.foo"), undefined); 51 | await new Promise(resolve => timeout(resolve)); 52 | assert.strictEqual(starts, 0); 53 | }); 54 | 55 | it("transition.on(\"start\", listener) registers a listener for the start event", async () => { 56 | const root = document.documentElement; 57 | const t = select(root).transition(); 58 | const schedule = root.__transition[t._id]; 59 | await new Promise(resolve => t.on("start", () => { 60 | assert.strictEqual(schedule.state, STARTING) 61 | resolve(); 62 | })); 63 | }); 64 | 65 | it("transition.on(\"interrupt\", listener) registers a listener for the interrupt event (during start)", async () => { 66 | const root = document.documentElement; 67 | const s = select(root); 68 | const t = s.transition(); 69 | const schedule = root.__transition[t._id]; 70 | timeout(() => s.interrupt()); 71 | await new Promise(resolve => t.on("interrupt", () => { 72 | assert.strictEqual(schedule.state, ENDED); 73 | resolve(); 74 | })); 75 | }); 76 | 77 | it("transition.on(\"interrupt\", listener) registers a listener for the interrupt event (during run)", async () => { 78 | const root = document.documentElement; 79 | const s = select(root); 80 | const t = s.transition(); 81 | const schedule = root.__transition[t._id]; 82 | timeout(() => s.interrupt(), 50); 83 | await new Promise(resolve => t.on("interrupt", () => { 84 | assert.strictEqual(schedule.state, ENDED); 85 | resolve(); 86 | })); 87 | }); 88 | 89 | it("transition.on(\"end\", listener) registers a listener for the end event", async () => { 90 | const root = document.documentElement; 91 | const t = select(root).transition().duration(50); 92 | const schedule = root.__transition[t._id]; 93 | await new Promise(resolve => t.on("end", () => { 94 | assert.strictEqual(schedule.state, ENDING); 95 | resolve(); 96 | })); 97 | }); 98 | 99 | it("transition.on(typename, listener) uses copy-on-write to apply changes", "

", async () => { 100 | const one = document.querySelector("#one"); 101 | const two = document.querySelector("#two"); 102 | const foo = () => {}; 103 | const bar = () => {}; 104 | const t = selectAll([one, two]).transition(); 105 | const schedule1 = one.__transition[t._id]; 106 | const schedule2 = two.__transition[t._id]; 107 | t.on("start", foo); 108 | assert.strictEqual(schedule1.on.on("start"), foo); 109 | assert.strictEqual(schedule2.on, schedule1.on); 110 | t.on("start", bar); 111 | assert.strictEqual(schedule1.on.on("start"), bar); 112 | assert.strictEqual(schedule2.on, schedule1.on); 113 | select(two).transition(t).on("start", foo); 114 | assert.strictEqual(schedule1.on.on("start"), bar); 115 | assert.strictEqual(schedule2.on.on("start"), foo); 116 | }); 117 | -------------------------------------------------------------------------------- /test/transition/remove-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select} from "d3-selection"; 3 | import {timeout} from "d3-timer"; 4 | import "../../src/index.js"; 5 | import it from "../jsdom.js"; 6 | 7 | it("transition.remove() creates an end listener to remove the element", async () => { 8 | const root = document.documentElement; 9 | const body = document.body; 10 | const s = select(body); 11 | const t = s.transition().remove().on("start", started).on("end", ended); 12 | const end = t.end(); 13 | 14 | function started() { 15 | assert.strictEqual(body.parentNode, root); 16 | } 17 | 18 | function ended() { 19 | assert.strictEqual(body.parentNode, null); 20 | } 21 | 22 | await new Promise(resolve => timeout(resolve)); 23 | assert.strictEqual(body.parentNode, root); 24 | await end; 25 | }); 26 | 27 | it("transition.remove() creates an end listener named end.remove", async () => { 28 | const root = document.documentElement; 29 | const body = document.body; 30 | const s = select(body); 31 | const t = s.transition().remove().on("start", started).on("end", ended); 32 | const end = t.end(); 33 | 34 | function started() { 35 | assert.strictEqual(body.parentNode, root); 36 | } 37 | 38 | function ended() { 39 | assert.strictEqual(body.parentNode, root); 40 | } 41 | 42 | t.on("end.remove").call(body); 43 | assert.strictEqual(body.parentNode, null); 44 | t.on("end.remove", null); 45 | root.appendChild(body); 46 | await end; 47 | }); 48 | -------------------------------------------------------------------------------- /test/transition/select-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selectAll} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.select(selector) selects the descendants matching the specified selector, then derives a transition", "

", () => { 7 | const one = document.querySelector("#one"); 8 | const two = document.querySelector("#two"); 9 | const t1 = selectAll([one, two]).data([1, 2]).transition().delay(function(d) { return d * 10; }); 10 | const t2 = t1.select("child"); 11 | assert.strictEqual(t2 instanceof transition, true); 12 | assert.deepStrictEqual(t2._groups, [[one.firstChild, two.firstChild]]); 13 | assert.strictEqual(t2._parents, t1._parents); 14 | assert.strictEqual(t2._name, t1._name); 15 | assert.strictEqual(t2._id, t1._id); 16 | assert.strictEqual(one.firstChild.__data__, 1); 17 | assert.strictEqual(two.firstChild.__data__, 2); 18 | assert.strictEqual(one.firstChild.__transition[t1._id].delay, 10); 19 | assert.strictEqual(two.firstChild.__transition[t1._id].delay, 20); 20 | }); 21 | 22 | it("transition.select(function) selects the descendants returned by the specified function, then derives a transition", "

", () => { 23 | const one = document.querySelector("#one"); 24 | const two = document.querySelector("#two"); 25 | const t1 = selectAll([one, two]).data([1, 2]).transition().delay(function(d) { return d * 10; }); 26 | const t2 = t1.select(function() { return this.firstChild; }); 27 | assert.strictEqual(t2 instanceof transition, true); 28 | assert.deepStrictEqual(t2._groups, [[one.firstChild, two.firstChild]]); 29 | assert.strictEqual(t2._parents, t1._parents); 30 | assert.strictEqual(t2._name, t1._name); 31 | assert.strictEqual(t2._id, t1._id); 32 | assert.strictEqual(one.firstChild.__data__, 1); 33 | assert.strictEqual(two.firstChild.__data__, 2); 34 | assert.strictEqual(one.firstChild.__transition[t1._id].delay, 10); 35 | assert.strictEqual(two.firstChild.__transition[t1._id].delay, 20); 36 | }); 37 | -------------------------------------------------------------------------------- /test/transition/selectAll-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selectAll} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.selectAll(selector) selects the descendants matching the specified selector, then derives a transition", "

", () => { 7 | const one = document.querySelector("#one"); 8 | const two = document.querySelector("#two"); 9 | const t1 = selectAll([one, two]).data([1, 2]).transition().delay(function(d) { return d * 10; }); 10 | const t2 = t1.selectAll("child"); 11 | assert.strictEqual(t2 instanceof transition, true); 12 | assert.deepStrictEqual(t2._groups.map(group => Array.from(group)), [[one.firstChild], [two.firstChild]]); 13 | assert.deepStrictEqual(t2._parents, [one, two]); 14 | assert.strictEqual(t2._name, t1._name); 15 | assert.strictEqual(t2._id, t1._id); 16 | assert.strictEqual("__data__" in one.firstChild, false); 17 | assert.strictEqual("__data__" in two.firstChild, false); 18 | assert.strictEqual(one.firstChild.__transition[t1._id].delay, 10); 19 | assert.strictEqual(two.firstChild.__transition[t1._id].delay, 20); 20 | }); 21 | 22 | it("transition.selectAll(function) selects the descendants returned by the specified function, then derives a transition", "

", () => { 23 | const one = document.querySelector("#one"); 24 | const two = document.querySelector("#two"); 25 | const t1 = selectAll([one, two]).data([1, 2]).transition().delay(function(d) { return d * 10; }); 26 | const t2 = t1.selectAll(function() { return [this.firstChild]; }); 27 | assert.strictEqual(t2 instanceof transition, true); 28 | assert.deepStrictEqual(t2._groups, [[one.firstChild], [two.firstChild]]); 29 | assert.deepStrictEqual(t2._parents, [one, two]); 30 | assert.strictEqual(t2._name, t1._name); 31 | assert.strictEqual(t2._id, t1._id); 32 | assert.strictEqual("__data__" in one.firstChild, false); 33 | assert.strictEqual("__data__" in two.firstChild, false); 34 | assert.strictEqual(one.firstChild.__transition[t1._id].delay, 10); 35 | assert.strictEqual(two.firstChild.__transition[t1._id].delay, 20); 36 | }); 37 | -------------------------------------------------------------------------------- /test/transition/selectChild-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selectAll} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.selectChild(selector) selects the child matching the specified selector, then derives a transition", "

", () => { 7 | const one = document.querySelector("#one"); 8 | const two = document.querySelector("#two"); 9 | const t1 = selectAll([one, two]).data([1, 2]).transition().delay(function(d) { return d * 10; }); 10 | const t2 = t1.selectChild("child"); 11 | assert.strictEqual(t2 instanceof transition, true); 12 | assert.deepStrictEqual(t2._groups, [[one.firstChild, two.firstChild]]); 13 | assert.strictEqual(t2._parents, t1._parents); 14 | assert.strictEqual(t2._name, t1._name); 15 | assert.strictEqual(t2._id, t1._id); 16 | assert.strictEqual(one.firstChild.__data__, 1); 17 | assert.strictEqual(two.firstChild.__data__, 2); 18 | assert.strictEqual(one.firstChild.__transition[t1._id].delay, 10); 19 | assert.strictEqual(two.firstChild.__transition[t1._id].delay, 20); 20 | }); 21 | -------------------------------------------------------------------------------- /test/transition/selectChildren-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {selectAll} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.selectChildren(selector) selects the children matching the specified selector, then derives a transition", "

", () => { 7 | const one = document.querySelector("#one"); 8 | const two = document.querySelector("#two"); 9 | const t1 = selectAll([one, two]).data([1, 2]).transition().delay(function(d) { return d * 10; }); 10 | const t2 = t1.selectChildren("child"); 11 | assert.strictEqual(t2 instanceof transition, true); 12 | assert.deepStrictEqual(t2._groups.map(group => Array.from(group)), [[one.firstChild], [two.firstChild]]); 13 | assert.deepStrictEqual(t2._parents, [one, two]); 14 | assert.strictEqual(t2._name, t1._name); 15 | assert.strictEqual(t2._id, t1._id); 16 | assert.strictEqual("__data__" in one.firstChild, false); 17 | assert.strictEqual("__data__" in two.firstChild, false); 18 | assert.strictEqual(one.firstChild.__transition[t1._id].delay, 10); 19 | assert.strictEqual(two.firstChild.__transition[t1._id].delay, 20); 20 | }); 21 | -------------------------------------------------------------------------------- /test/transition/selection-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select, selection} from "d3-selection"; 3 | import "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.selection() returns the transition’s selection", "

one

two

", () => { 7 | const s0 = select(document.body).selectAll("h1"); 8 | const t = s0.transition(); 9 | const s1 = t.selection(); 10 | assert(s1 instanceof selection); 11 | assert.strictEqual(s1._groups, s0._groups); 12 | assert.strictEqual(s1._parents, s0._parents); 13 | }); 14 | -------------------------------------------------------------------------------- /test/transition/size-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select, selectAll, selection} from "d3-selection"; 3 | import {transition} from "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.size is the same as selection.size", () => { 7 | assert.strictEqual(transition.prototype.size, selection.prototype.size); 8 | }); 9 | 10 | it("transition.size() returns the expected value", () => { 11 | const root = document.documentElement; 12 | assert.strictEqual(select(root).transition().size(), 1); 13 | assert.strictEqual(selectAll([null, root]).transition().size(), 1); 14 | }); 15 | -------------------------------------------------------------------------------- /test/transition/style-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easeCubic} from "d3-ease"; 3 | import {interpolateNumber, interpolateRgb, interpolateString} from "d3-interpolate"; 4 | import {select, selectAll} from "d3-selection"; 5 | import {timeout} from "d3-timer"; 6 | import "../../src/index.js"; 7 | import it from "../jsdom.js"; 8 | 9 | it("transition.style(name, value) creates an tween to the specified value", async () => { 10 | const root = document.documentElement; 11 | const ease = easeCubic; 12 | const duration = 250; 13 | const interpolate = interpolateRgb("red", "blue"); 14 | const s = select(root).style("color", "red"); 15 | s.transition().style("color", "blue"); 16 | await new Promise(resolve => timeout(elapsed => { 17 | assert.strictEqual(root.style.getPropertyValue("color"), interpolate(ease(elapsed / duration))); 18 | resolve(); 19 | }, 125)); 20 | }); 21 | 22 | it("transition.style(name, value) creates an tween to the value returned by the specified function", async () => { 23 | const root = document.documentElement; 24 | const ease = easeCubic; 25 | const duration = 250; 26 | const interpolate = interpolateRgb("red", "blue"); 27 | const s = select(root).style("color", "red"); 28 | s.transition().style("color", () => "blue"); 29 | await new Promise(resolve => timeout(elapsed => { 30 | assert.strictEqual(root.style.getPropertyValue("color"), interpolate(ease(elapsed / duration))); 31 | resolve(); 32 | }, 125)); 33 | }); 34 | 35 | it("transition.style(name, value) immediately evaluates the specified function with the expected context and arguments", "

", async () => { 36 | const one = document.querySelector("#one"); 37 | const two = document.querySelector("#two"); 38 | const ease = easeCubic; 39 | const duration = 250; 40 | const interpolate1 = interpolateRgb("cyan", "red"); 41 | const interpolate2 = interpolateRgb("magenta", "green"); 42 | const t = selectAll([one, two]).data(["red", "green"]); 43 | const result = []; 44 | t.transition().style("color", function(d, i, nodes) { result.push([d, i, nodes, this]); return d; }); 45 | assert.deepStrictEqual(result, [ 46 | ["red", 0, [one, two], one], 47 | ["green", 1, [one, two], two] 48 | ]); 49 | await new Promise(resolve => timeout(elapsed => { 50 | assert.strictEqual(one.style.getPropertyValue("color"), interpolate1(ease(elapsed / duration))); 51 | assert.strictEqual(two.style.getPropertyValue("color"), interpolate2(ease(elapsed / duration))); 52 | resolve(); 53 | }, 125)); 54 | }); 55 | 56 | it("transition.style(name, value) recycles tweens ", "

", () => { 57 | const one = document.querySelector("#one"); 58 | const two = document.querySelector("#two"); 59 | const t = selectAll([one, two]).transition().style("color", "red"); 60 | assert.strictEqual(one.__transition[t._id].tween, two.__transition[t._id].tween); 61 | }); 62 | 63 | it("transition.style(name, value) constructs an interpolator using the current value on start", async () => { 64 | const root = document.documentElement; 65 | const ease = easeCubic; 66 | const duration = 250; 67 | const interpolate = interpolateRgb("red", "blue"); 68 | const s = select(root); 69 | s.transition().on("start", () => { s.style("color", "red"); }).style("color", () => "blue"); 70 | await new Promise(resolve => timeout(elapsed => { 71 | assert.strictEqual(root.style.getPropertyValue("color"), interpolate(ease(elapsed / duration))); 72 | resolve(); 73 | }, 125)); 74 | }); 75 | 76 | it("transition.style(name, null) creates an tween which removes the specified style post-start", async () => { 77 | const root = document.documentElement; 78 | const started = () => assert.strictEqual(root.style.getPropertyValue("color"), "red"); 79 | const s = select(root).style("color", "red"); 80 | s.transition().style("color", null).on("start", started); 81 | await new Promise(resolve => timeout(() => { 82 | assert.strictEqual(root.style.getPropertyValue("color"), ""); 83 | resolve(); 84 | })); 85 | }); 86 | 87 | it("transition.style(name, null) creates an tween which removes the specified style post-start", async () => { 88 | const root = document.documentElement; 89 | const started = () => assert.strictEqual(root.style.getPropertyValue("color"), "red"); 90 | const selection = select(root).style("color", "red"); 91 | selection.transition().style("color", () => null).on("start", started); 92 | await new Promise(resolve => timeout(() => { 93 | assert.strictEqual(root.style.getPropertyValue("color"), ""); 94 | resolve(); 95 | })); 96 | }); 97 | 98 | it("transition.style(name, value) creates an tween which removes the specified style post-start if the specified function returns null", async () => { 99 | const root = document.documentElement; 100 | const started = () => assert.strictEqual(root.style.getPropertyValue("color"), "red"); 101 | const selection = select(root).style("color", "red"); 102 | selection.transition().style("color", function() {}).on("start", started); 103 | await new Promise(resolve => timeout(() => { 104 | assert.strictEqual(root.style.getPropertyValue("color"), ""); 105 | resolve(); 106 | })); 107 | }); 108 | 109 | it("transition.style(name, constant) is a noop if the string-coerced value matches the current value on tween initialization", async () => { 110 | const root = document.documentElement; 111 | const selection = select(root).style("opacity", 1); 112 | selection.transition().style("opacity", 1); 113 | timeout(() => { root.style.opacity = 0.5; }, 125); 114 | await new Promise(resolve => timeout(() => { 115 | assert.strictEqual(root.style.getPropertyValue("opacity"), "0.5"); 116 | resolve(); 117 | }, 250)); 118 | }); 119 | 120 | it("transition.style(name, function) is a noop if the string-coerced value matches the current value on tween initialization", async () => { 121 | const root = document.documentElement; 122 | const selection = select(root).style("opacity", 1); 123 | selection.transition().style("opacity", function() { return 1; }); 124 | timeout(() => { root.style.opacity = 0.5; }, 125); 125 | await new Promise(resolve => timeout(() => { 126 | assert.strictEqual(root.style.getPropertyValue("opacity"), "0.5"); 127 | resolve(); 128 | }, 250)); 129 | }); 130 | 131 | it("transition.style(name, value) interpolates numbers", async () => { 132 | const root = document.documentElement; 133 | const ease = easeCubic; 134 | const duration = 250; 135 | const interpolate = interpolateNumber(0, 1); 136 | const s = select(root).style("opacity", 0); 137 | s.transition().style("opacity", 1); 138 | await new Promise(resolve => timeout(elapsed => { 139 | assert.strictEqual(root.style.getPropertyValue("opacity"), interpolate(ease(elapsed / duration)) + ""); 140 | resolve(); 141 | }, 125)); 142 | }); 143 | 144 | it("transition.style(name, constant) uses interpolateNumber if value is a number", async () => { 145 | const root = document.documentElement; 146 | const s = select(root).style("font-size", "15px"); 147 | s.transition().style("font-size", 10); 148 | await new Promise(resolve => timeout(() => { 149 | assert.strictEqual(root.style.getPropertyValue("font-size"), "15px"); // ignores NaN 150 | resolve(); 151 | }, 125)); 152 | }); 153 | 154 | it("transition.style(name, function) uses interpolateNumber if value is a number", async () => { 155 | const root = document.documentElement; 156 | const s = select(root).style("font-size", "15px"); 157 | s.transition().style("font-size", () => 10); 158 | await new Promise(resolve => timeout(() => { 159 | assert.strictEqual(root.style.getPropertyValue("font-size"), "15px"); // ignores NaN 160 | resolve(); 161 | }, 125)); 162 | }); 163 | 164 | it("transition.style(name, value) interpolates strings", async () => { 165 | const root = document.documentElement; 166 | const ease = easeCubic; 167 | const duration = 250; 168 | const interpolate = interpolateString("1px", "2px"); 169 | const s = select(root).style("font-size", "1px"); 170 | s.transition().style("font-size", "2px"); 171 | await new Promise(resolve => timeout(elapsed => { 172 | assert.strictEqual(root.style.getPropertyValue("font-size"), interpolate(ease(elapsed / duration))); 173 | resolve(); 174 | }, 125)); 175 | }); 176 | 177 | it("transition.style(name, value) interpolates colors", async () => { 178 | const root = document.documentElement; 179 | const ease = easeCubic; 180 | const duration = 250; 181 | const interpolate = interpolateRgb("#f00", "#00f"); 182 | const s = select(root).style("color", "#f00"); 183 | s.transition().style("color", "#00f"); 184 | await new Promise(resolve => timeout(elapsed => { 185 | assert.strictEqual(root.style.getPropertyValue("color"), interpolate(ease(elapsed / duration))); 186 | resolve(); 187 | }, 125)); 188 | }); 189 | 190 | it("transition.style(name, value) creates an styleTween with the specified name", async () => { 191 | const root = document.documentElement; 192 | const s = select(root).style("color", "red"); 193 | const t = s.transition().style("color", "blue"); 194 | assert.strictEqual(t.styleTween("color").call(root).call(root, 0.5), "rgb(128, 0, 128)"); 195 | }); 196 | 197 | it("transition.style(name, value) creates a tween with the name \"style.name\"", async () => { 198 | const root = document.documentElement; 199 | const s = select(root).style("color", "red"); 200 | const t = s.transition().style("color", "blue"); 201 | t.tween("style.color").call(root).call(root, 0.5); 202 | assert.strictEqual(root.style.getPropertyValue("color"), "rgb(128, 0, 128)"); 203 | }); 204 | -------------------------------------------------------------------------------- /test/transition/styleTween-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easeCubic} from "d3-ease"; 3 | import {interpolateHcl} from "d3-interpolate"; 4 | import {select, selectAll} from "d3-selection"; 5 | import {now, timeout} from "d3-timer"; 6 | import "../../src/index.js"; 7 | import {ENDING} from "../../src/transition/schedule.js"; 8 | import it from "../jsdom.js"; 9 | 10 | it("transition.styleTween(name, value) defines a style tween using the interpolator returned by the specified function", async () => { 11 | const root = document.documentElement; 12 | const interpolate = interpolateHcl("red", "blue"); 13 | const ease = easeCubic; 14 | select(root).transition().styleTween("color", () => interpolate); 15 | await new Promise(resolve => timeout(elapsed => { 16 | assert.deepStrictEqual(root.style.getPropertyValue("color"), interpolate(ease(elapsed / 250))); 17 | assert.deepStrictEqual(root.style.getPropertyPriority("color"), ""); 18 | resolve(); 19 | }, 125)); 20 | }); 21 | 22 | it("transition.styleTween(name, value, priority) defines a style tween using the interpolator returned by the specified function", async () => { 23 | const root = document.documentElement; 24 | const interpolate = interpolateHcl("red", "blue"); 25 | const ease = easeCubic; 26 | select(root).transition().styleTween("color", () => interpolate, "important"); 27 | await new Promise(resolve => timeout(elapsed => { 28 | assert.deepStrictEqual(root.style.getPropertyValue("color"), interpolate(ease(elapsed / 250))); 29 | assert.deepStrictEqual(root.style.getPropertyPriority("color"), "important"); 30 | resolve(); 31 | }, 125)); 32 | }); 33 | 34 | it("transition.styleTween(name, value) invokes the value function with the expected context and arguments", "

", async () => { 35 | const one = document.querySelector("#one"); 36 | const two = document.querySelector("#two"); 37 | const result = []; 38 | selectAll([one, two]).data(["one", "two"]).transition().styleTween("color", function(d, i, nodes) { result.push([d, i, nodes, this]); }); 39 | await new Promise(resolve => timeout(resolve)); 40 | assert.deepStrictEqual(result, [ 41 | ["one", 0, [one, two], one], 42 | ["two", 1, [one, two], two] 43 | ]); 44 | }); 45 | 46 | it("transition.styleTween(name, value) passes the eased time to the interpolator", async () => { 47 | const root = document.documentElement; 48 | const then = now(); 49 | const duration = 250; 50 | const ease = easeCubic; 51 | const t = select(root).transition().styleTween("color", () => interpolate); 52 | const schedule = root.__transition[t._id]; 53 | function interpolate(t) { 54 | assert.strictEqual(this, root); 55 | assert.strictEqual(t, schedule.state === ENDING ? 1 : ease((now() - then) / duration)); 56 | } 57 | await t.end(); 58 | }); 59 | 60 | it("transition.styleTween(name, value) allows the specified function to return null for a noop", async () => { 61 | const root = document.documentElement; 62 | const s = select(root).style("color", "red"); 63 | s.transition().styleTween("color", () => {}); 64 | await new Promise(resolve => timeout(() => { 65 | assert.deepStrictEqual(root.style.getPropertyValue("color"), "red"); 66 | resolve(); 67 | }, 125)); 68 | }); 69 | 70 | it("transition.styleTween(name, value) coerces the specified name to a string", async () => { 71 | const root = document.documentElement; 72 | const interpolate = interpolateHcl("red", "blue"); 73 | const ease = easeCubic; 74 | select(root).transition().styleTween({toString() { return "color"; }}, () => interpolate); 75 | await new Promise(resolve => timeout(elapsed => { 76 | assert.deepStrictEqual(root.style.getPropertyValue("color"), interpolate(ease(elapsed / 250))); 77 | resolve(); 78 | }, 125)); 79 | }); 80 | 81 | it("transition.styleTween(name, value) throws an error if value is not null and not a function", async () => { 82 | const root = document.documentElement; 83 | const t = select(root).transition(); 84 | assert.throws(() => { t.styleTween("color", 42); }); 85 | }); 86 | 87 | it("transition.styleTween(name, null) removes the specified style tween", async () => { 88 | const root = document.documentElement; 89 | const interpolate = interpolateHcl("red", "blue"); 90 | const t = select(root).transition().styleTween("color", () => interpolate).styleTween("color", null); 91 | assert.strictEqual(t.styleTween("color"), null); 92 | assert.strictEqual(t.tween("style.color"), null); 93 | await new Promise(resolve => timeout(() => { 94 | assert.strictEqual(root.style.getPropertyValue("color"), ""); 95 | resolve(); 96 | }, 125)); 97 | }); 98 | 99 | it("transition.styleTween(name) returns the style tween with the specified name", async () => { 100 | const root = document.documentElement; 101 | const interpolate = interpolateHcl("red", "blue"); 102 | const tween = () => interpolate; 103 | const started = () => { assert.strictEqual(t.styleTween("color"), tween); }; 104 | const ended = () => { assert.strictEqual(t.styleTween("color"), tween); }; 105 | const t = select(root).transition().styleTween("color", tween).on("start", started).on("end", ended); 106 | assert.strictEqual(t.styleTween("color"), tween); 107 | assert.strictEqual(t.styleTween("bar"), null); 108 | await t.end(); 109 | }); 110 | 111 | it("transition.styleTween(name) coerces the specified name to a string", async () => { 112 | const root = document.documentElement; 113 | const tween = () => {}; 114 | const t = select(root).transition().styleTween("color", tween); 115 | assert.strictEqual(t.styleTween({toString() { return "color"; }}), tween); 116 | }); 117 | -------------------------------------------------------------------------------- /test/transition/text-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select, selectAll} from "d3-selection"; 3 | import "../../src/index.js"; 4 | import it from "../jsdom.js"; 5 | 6 | it("transition.text(value) creates a tween to set the text content to the specified value post-start", async () => { 7 | const root = document.documentElement; 8 | const s = select(root); 9 | const t = s.transition().text("hello"); 10 | 11 | await new Promise(resolve => t.on("start", () => { 12 | assert.strictEqual(root.textContent, ""); 13 | resolve(); 14 | })); 15 | 16 | assert.strictEqual(root.textContent, "hello"); 17 | }); 18 | 19 | it("transition.text(value) creates a tween to set the text content to the value returned by the specified function post-start", async () => { 20 | const root = document.documentElement; 21 | const s = select(root); 22 | const t = s.transition().text(() => "hello"); 23 | 24 | await new Promise(resolve => t.on("start", () => { 25 | assert.strictEqual(root.textContent, ""); 26 | resolve(); 27 | })); 28 | 29 | assert.strictEqual(root.textContent, "hello"); 30 | }); 31 | 32 | it("transition.text(value) immediately evaluates the specified function with the expected context and arguments", "

", async () => { 33 | const one = document.querySelector("#one"); 34 | const two = document.querySelector("#two"); 35 | const s = selectAll([one, two]).data(["red", "green"]); 36 | const result = []; 37 | const t = s.transition().text(function(d, i, nodes) { result.push([d, i, nodes, this]); return d; }); 38 | 39 | assert.deepStrictEqual(result, [ 40 | ["red", 0, [one, two], one], 41 | ["green", 1, [one, two], two] 42 | ]); 43 | 44 | await new Promise(resolve => t.on("start", resolve)); 45 | assert.strictEqual(one.textContent, "red"); 46 | assert.strictEqual(two.textContent, "green"); 47 | }); 48 | 49 | it("transition.text(value) creates a tween with the name \"text\"", () => { 50 | const root = document.documentElement; 51 | const s = select(root); 52 | const t = s.transition().text("hello"); 53 | assert.strictEqual(t.tween("text").call(root), undefined); 54 | assert.strictEqual(root.textContent, "hello"); 55 | }); 56 | -------------------------------------------------------------------------------- /test/transition/textTween-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easeCubic} from "d3-ease"; 3 | import {interpolateHcl} from "d3-interpolate"; 4 | import {select} from "d3-selection"; 5 | import {timeout} from "d3-timer"; 6 | import "../../src/index.js"; 7 | import it from "../jsdom.js"; 8 | 9 | it("transition.textTween(value) defines a text tween using the interpolator returned by the specified function", async () => { 10 | const root = document.documentElement; 11 | const interpolate = interpolateHcl("red", "blue"); 12 | const ease = easeCubic; 13 | select(root).transition().textTween(() => interpolate); 14 | await new Promise(resolve => timeout(elapsed => { 15 | assert.deepStrictEqual(root.textContent, interpolate(ease(elapsed / 250))); 16 | resolve(); 17 | }, 125)); 18 | }); 19 | 20 | it("transition.textTween() returns the existing text tween", () => { 21 | const root = document.documentElement; 22 | const factory = () => {}; 23 | const t = select(root).transition().textTween(factory); 24 | assert.strictEqual(t.textTween(), factory); 25 | }); 26 | 27 | it("transition.textTween(null) removes an existing text tween", () => { 28 | const root = document.documentElement; 29 | const factory = () => {}; 30 | const t = select(root).transition().textTween(factory); 31 | t.textTween(undefined); 32 | assert.strictEqual(t.textTween(), null); 33 | }); 34 | -------------------------------------------------------------------------------- /test/transition/transition-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {select} from "d3-selection"; 3 | import {timeout} from "d3-timer"; 4 | import "../../src/index.js"; 5 | import it from "../jsdom.js"; 6 | 7 | it("transition.transition() allows preceeding transitions with zero duration to end naturally", async () => { 8 | let end0 = false; 9 | let end1 = false; 10 | let end2 = false; 11 | const s = select(document.documentElement); 12 | const t = s.transition().duration(0).on("end", () => { end0 = true; }); 13 | s.transition().duration(0).on("end", () => { end1 = true; }); 14 | t.transition().duration(0).on("end", () => { end2 = true; }); 15 | await new Promise(resolve => timeout(resolve, 50)); 16 | assert.strictEqual(end0, true); 17 | assert.strictEqual(end1, true); 18 | assert.strictEqual(end2, true); 19 | }); 20 | -------------------------------------------------------------------------------- /test/transition/tween-test.js: -------------------------------------------------------------------------------- 1 | import assert from "assert"; 2 | import {easeCubic} from "d3-ease"; 3 | import {select, selectAll} from "d3-selection"; 4 | import {now, timeout} from "d3-timer"; 5 | import "../../src/index.js"; 6 | import {ENDING} from "../../src/transition/schedule.js"; 7 | import it from "../jsdom.js"; 8 | 9 | it("transition.tween(name, value) defines an tween using the interpolator returned by the specified function", async () => { 10 | const root = document.documentElement; 11 | let value; 12 | const interpolate = t => { value = t; }; 13 | select(root).transition().tween("foo", () => interpolate); 14 | await new Promise(resolve => timeout(elapsed => { 15 | assert.strictEqual(value, easeCubic(elapsed / 250)); 16 | resolve(); 17 | }, 125)); 18 | }); 19 | 20 | it("transition.tween(name, value) invokes the value function with the expected context and arguments", "

", async () => { 21 | const one = document.querySelector("#one"); 22 | const two = document.querySelector("#two"); 23 | const result = []; 24 | selectAll([one, two]).data(["one", "two"]).transition().tween("foo", function(d, i, nodes) { result.push([d, i, nodes, this]); }); 25 | await new Promise(resolve => timeout(resolve)); 26 | assert.deepStrictEqual(result, [ 27 | ["one", 0, [one, two], one], 28 | ["two", 1, [one, two], two] 29 | ]); 30 | }); 31 | 32 | it("transition.tween(name, value) passes the eased time to the interpolator", async () => { 33 | const root = document.documentElement; 34 | const then = now(); 35 | const duration = 250; 36 | const ease = easeCubic; 37 | const t = select(root).transition().tween("foo", () => interpolate); 38 | const schedule = root.__transition[t._id]; 39 | function interpolate(t) { 40 | assert.strictEqual(this, root); 41 | assert.strictEqual(t, schedule.state === ENDING ? 1 : ease((now() - then) / duration)); 42 | } 43 | await t.end(); 44 | }); 45 | 46 | it("transition.tween(name, value) allows the specified function to return null for a noop", async () => { 47 | const root = document.documentElement; 48 | const s = select(root); 49 | s.transition().tween("foo", () => {}); 50 | }); 51 | 52 | it("transition.tween(name, value) uses copy-on-write to apply changes", "

", async () => { 53 | const one = document.querySelector("#one"); 54 | const two = document.querySelector("#two"); 55 | const foo = () => {}; 56 | const bar = () => {}; 57 | const t = selectAll([one, two]).transition(); 58 | const schedule1 = one.__transition[t._id]; 59 | const schedule2 = two.__transition[t._id]; 60 | t.tween("foo", foo); 61 | assert.deepStrictEqual(schedule1.tween, [{name: "foo", value: foo}]); 62 | assert.strictEqual(schedule2.tween, schedule1.tween); 63 | t.tween("foo", bar); 64 | assert.deepStrictEqual(schedule1.tween, [{name: "foo", value: bar}]); 65 | assert.strictEqual(schedule2.tween, schedule1.tween); 66 | select(two).transition(t).tween("foo", foo); 67 | assert.deepStrictEqual(schedule1.tween, [{name: "foo", value: bar}]); 68 | assert.deepStrictEqual(schedule2.tween, [{name: "foo", value: foo}]); 69 | }); 70 | 71 | it("transition.tween(name, value) uses copy-on-write to apply removals", "

", async () => { 72 | const one = document.querySelector("#one"); 73 | const two = document.querySelector("#two"); 74 | const foo = () => {}; 75 | const t = selectAll([one, two]).transition(); 76 | const schedule1 = one.__transition[t._id]; 77 | const schedule2 = two.__transition[t._id]; 78 | t.tween("foo", foo); 79 | assert.deepStrictEqual(schedule1.tween, [{name: "foo", value: foo}]); 80 | assert.strictEqual(schedule2.tween, schedule1.tween); 81 | t.tween("bar", null); 82 | assert.deepStrictEqual(schedule1.tween, [{name: "foo", value: foo}]); 83 | assert.strictEqual(schedule2.tween, schedule1.tween); 84 | t.tween("foo", null); 85 | assert.deepStrictEqual(schedule1.tween, []); 86 | assert.strictEqual(schedule2.tween, schedule1.tween); 87 | select(two).transition(t).tween("foo", foo); 88 | assert.deepStrictEqual(schedule1.tween, []); 89 | assert.deepStrictEqual(schedule2.tween, [{name: "foo", value: foo}]); 90 | }); 91 | 92 | it("transition.tween(name, value) coerces the specified name to a string", async () => { 93 | const root = document.documentElement; 94 | const tween = () => {}; 95 | const t = select(root).transition().tween({toString() { return "foo"; }}, tween); 96 | assert.strictEqual(t.tween("foo"), tween); 97 | }); 98 | 99 | it("transition.tween(name) coerces the specified name to a string", async () => { 100 | const root = document.documentElement; 101 | const tween = () => {}; 102 | const t = select(root).transition().tween("foo", tween); 103 | assert.strictEqual(t.tween({toString() { return "foo"; }}), tween); 104 | }); 105 | 106 | it("transition.tween(name, value) throws an error if value is not null and not a function", async () => { 107 | const root = document.documentElement; 108 | const t = select(root).transition(); 109 | assert.throws(() => { t.tween("foo", 42); }); 110 | }); 111 | 112 | it("transition.tween(name, null) removes the specified tween", async () => { 113 | const root = document.documentElement; 114 | let frames = 0; 115 | const interpolate = () => { ++frames; }; 116 | const t = select(root).transition().tween("foo", () => interpolate).tween("foo", null); 117 | assert.strictEqual(t.tween("foo"), null); 118 | await new Promise(resolve => timeout(() => { 119 | assert.strictEqual(frames, 0); 120 | resolve(); 121 | }, 125)); 122 | }); 123 | 124 | it("transition.tween(name) returns the tween with the specified name", async () => { 125 | const root = document.documentElement; 126 | const tween = () => {}; 127 | const started = () => { assert.strictEqual(t.tween("foo"), tween); } 128 | const ended = () => { assert.strictEqual(t.tween("foo"), tween); } 129 | const t = select(root).transition().tween("foo", tween).on("start", started).on("end", ended); 130 | assert.strictEqual(t.tween("foo"), tween); 131 | assert.strictEqual(t.tween("bar"), null); 132 | await t.end(); 133 | }); 134 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@7.12.11": 6 | version "7.12.11" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" 8 | integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== 9 | dependencies: 10 | "@babel/highlight" "^7.10.4" 11 | 12 | "@babel/code-frame@^7.10.4": 13 | version "7.14.5" 14 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" 15 | integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== 16 | dependencies: 17 | "@babel/highlight" "^7.14.5" 18 | 19 | "@babel/helper-validator-identifier@^7.14.5": 20 | version "7.14.5" 21 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" 22 | integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== 23 | 24 | "@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": 25 | version "7.14.5" 26 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" 27 | integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== 28 | dependencies: 29 | "@babel/helper-validator-identifier" "^7.14.5" 30 | chalk "^2.0.0" 31 | js-tokens "^4.0.0" 32 | 33 | "@eslint/eslintrc@^0.4.2": 34 | version "0.4.2" 35 | resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179" 36 | integrity sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg== 37 | dependencies: 38 | ajv "^6.12.4" 39 | debug "^4.1.1" 40 | espree "^7.3.0" 41 | globals "^13.9.0" 42 | ignore "^4.0.6" 43 | import-fresh "^3.2.1" 44 | js-yaml "^3.13.1" 45 | minimatch "^3.0.4" 46 | strip-json-comments "^3.1.1" 47 | 48 | "@tootallnate/once@1": 49 | version "1.1.2" 50 | resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" 51 | integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== 52 | 53 | "@types/node@*": 54 | version "15.12.2" 55 | resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.2.tgz#1f2b42c4be7156ff4a6f914b2fb03d05fa84e38d" 56 | integrity sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww== 57 | 58 | "@ungap/promise-all-settled@1.1.2": 59 | version "1.1.2" 60 | resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" 61 | integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== 62 | 63 | abab@^2.0.3, abab@^2.0.5: 64 | version "2.0.5" 65 | resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" 66 | integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== 67 | 68 | acorn-globals@^6.0.0: 69 | version "6.0.0" 70 | resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" 71 | integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== 72 | dependencies: 73 | acorn "^7.1.1" 74 | acorn-walk "^7.1.1" 75 | 76 | acorn-jsx@^5.3.1: 77 | version "5.3.1" 78 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" 79 | integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== 80 | 81 | acorn-walk@^7.1.1: 82 | version "7.2.0" 83 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" 84 | integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== 85 | 86 | acorn@^7.1.1, acorn@^7.4.0: 87 | version "7.4.1" 88 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" 89 | integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== 90 | 91 | acorn@^8.2.4: 92 | version "8.3.0" 93 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.3.0.tgz#1193f9b96c4e8232f00b11a9edff81b2c8b98b88" 94 | integrity sha512-tqPKHZ5CaBJw0Xmy0ZZvLs1qTV+BNFSyvn77ASXkpBNfIRk8ev26fKrD9iLGwGA9zedPao52GSHzq8lyZG0NUw== 95 | 96 | agent-base@6: 97 | version "6.0.2" 98 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" 99 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== 100 | dependencies: 101 | debug "4" 102 | 103 | ajv@^6.10.0, ajv@^6.12.4: 104 | version "6.12.6" 105 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 106 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 107 | dependencies: 108 | fast-deep-equal "^3.1.1" 109 | fast-json-stable-stringify "^2.0.0" 110 | json-schema-traverse "^0.4.1" 111 | uri-js "^4.2.2" 112 | 113 | ajv@^8.0.1: 114 | version "8.6.0" 115 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.0.tgz#60cc45d9c46a477d80d92c48076d972c342e5720" 116 | integrity sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ== 117 | dependencies: 118 | fast-deep-equal "^3.1.1" 119 | json-schema-traverse "^1.0.0" 120 | require-from-string "^2.0.2" 121 | uri-js "^4.2.2" 122 | 123 | ansi-colors@4.1.1, ansi-colors@^4.1.1: 124 | version "4.1.1" 125 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 126 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 127 | 128 | ansi-regex@^3.0.0: 129 | version "3.0.0" 130 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 131 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 132 | 133 | ansi-regex@^5.0.0: 134 | version "5.0.0" 135 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 136 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 137 | 138 | ansi-styles@^3.2.1: 139 | version "3.2.1" 140 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 141 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 142 | dependencies: 143 | color-convert "^1.9.0" 144 | 145 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 146 | version "4.3.0" 147 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 148 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 149 | dependencies: 150 | color-convert "^2.0.1" 151 | 152 | anymatch@~3.1.1: 153 | version "3.1.2" 154 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" 155 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== 156 | dependencies: 157 | normalize-path "^3.0.0" 158 | picomatch "^2.0.4" 159 | 160 | argparse@^1.0.7: 161 | version "1.0.10" 162 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 163 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 164 | dependencies: 165 | sprintf-js "~1.0.2" 166 | 167 | argparse@^2.0.1: 168 | version "2.0.1" 169 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 170 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 171 | 172 | astral-regex@^2.0.0: 173 | version "2.0.0" 174 | resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" 175 | integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== 176 | 177 | asynckit@^0.4.0: 178 | version "0.4.0" 179 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 180 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 181 | 182 | balanced-match@^1.0.0: 183 | version "1.0.2" 184 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 185 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 186 | 187 | binary-extensions@^2.0.0: 188 | version "2.2.0" 189 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 190 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 191 | 192 | brace-expansion@^1.1.7: 193 | version "1.1.11" 194 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 195 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 196 | dependencies: 197 | balanced-match "^1.0.0" 198 | concat-map "0.0.1" 199 | 200 | braces@~3.0.2: 201 | version "3.0.2" 202 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 203 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 204 | dependencies: 205 | fill-range "^7.0.1" 206 | 207 | browser-process-hrtime@^1.0.0: 208 | version "1.0.0" 209 | resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" 210 | integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== 211 | 212 | browser-stdout@1.3.1: 213 | version "1.3.1" 214 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 215 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 216 | 217 | buffer-from@^1.0.0: 218 | version "1.1.1" 219 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 220 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 221 | 222 | callsites@^3.0.0: 223 | version "3.1.0" 224 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 225 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 226 | 227 | camelcase@^6.0.0: 228 | version "6.2.0" 229 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" 230 | integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== 231 | 232 | chalk@^2.0.0: 233 | version "2.4.2" 234 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 235 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 236 | dependencies: 237 | ansi-styles "^3.2.1" 238 | escape-string-regexp "^1.0.5" 239 | supports-color "^5.3.0" 240 | 241 | chalk@^4.0.0, chalk@^4.1.0: 242 | version "4.1.1" 243 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" 244 | integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== 245 | dependencies: 246 | ansi-styles "^4.1.0" 247 | supports-color "^7.1.0" 248 | 249 | chokidar@3.5.1: 250 | version "3.5.1" 251 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" 252 | integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== 253 | dependencies: 254 | anymatch "~3.1.1" 255 | braces "~3.0.2" 256 | glob-parent "~5.1.0" 257 | is-binary-path "~2.1.0" 258 | is-glob "~4.0.1" 259 | normalize-path "~3.0.0" 260 | readdirp "~3.5.0" 261 | optionalDependencies: 262 | fsevents "~2.3.1" 263 | 264 | cliui@^7.0.2: 265 | version "7.0.4" 266 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 267 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 268 | dependencies: 269 | string-width "^4.2.0" 270 | strip-ansi "^6.0.0" 271 | wrap-ansi "^7.0.0" 272 | 273 | color-convert@^1.9.0: 274 | version "1.9.3" 275 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 276 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 277 | dependencies: 278 | color-name "1.1.3" 279 | 280 | color-convert@^2.0.1: 281 | version "2.0.1" 282 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 283 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 284 | dependencies: 285 | color-name "~1.1.4" 286 | 287 | color-name@1.1.3: 288 | version "1.1.3" 289 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 290 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 291 | 292 | color-name@~1.1.4: 293 | version "1.1.4" 294 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 295 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 296 | 297 | combined-stream@^1.0.8: 298 | version "1.0.8" 299 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 300 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 301 | dependencies: 302 | delayed-stream "~1.0.0" 303 | 304 | commander@^2.20.0: 305 | version "2.20.3" 306 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 307 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 308 | 309 | concat-map@0.0.1: 310 | version "0.0.1" 311 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 312 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 313 | 314 | cross-spawn@^7.0.2: 315 | version "7.0.3" 316 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 317 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 318 | dependencies: 319 | path-key "^3.1.0" 320 | shebang-command "^2.0.0" 321 | which "^2.0.1" 322 | 323 | cssom@^0.4.4: 324 | version "0.4.4" 325 | resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" 326 | integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== 327 | 328 | cssom@~0.3.6: 329 | version "0.3.8" 330 | resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" 331 | integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== 332 | 333 | cssstyle@^2.3.0: 334 | version "2.3.0" 335 | resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" 336 | integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== 337 | dependencies: 338 | cssom "~0.3.6" 339 | 340 | "d3-color@1 - 3": 341 | version "3.0.1" 342 | resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.0.1.tgz#03316e595955d1fcd39d9f3610ad41bb90194d0a" 343 | integrity sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw== 344 | 345 | "d3-dispatch@1 - 3": 346 | version "3.0.1" 347 | resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" 348 | integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== 349 | 350 | "d3-ease@1 - 3": 351 | version "3.0.1" 352 | resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" 353 | integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== 354 | 355 | "d3-interpolate@1 - 3": 356 | version "3.0.1" 357 | resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" 358 | integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== 359 | dependencies: 360 | d3-color "1 - 3" 361 | 362 | "d3-selection@2 - 3": 363 | version "3.0.0" 364 | resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" 365 | integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== 366 | 367 | "d3-timer@1 - 3": 368 | version "3.0.1" 369 | resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" 370 | integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== 371 | 372 | data-urls@^2.0.0: 373 | version "2.0.0" 374 | resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" 375 | integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== 376 | dependencies: 377 | abab "^2.0.3" 378 | whatwg-mimetype "^2.3.0" 379 | whatwg-url "^8.0.0" 380 | 381 | debug@4, debug@4.3.1, debug@^4.0.1, debug@^4.1.1: 382 | version "4.3.1" 383 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" 384 | integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== 385 | dependencies: 386 | ms "2.1.2" 387 | 388 | decamelize@^4.0.0: 389 | version "4.0.0" 390 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 391 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 392 | 393 | decimal.js@^10.2.1: 394 | version "10.2.1" 395 | resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" 396 | integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== 397 | 398 | deep-is@^0.1.3, deep-is@~0.1.3: 399 | version "0.1.3" 400 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 401 | integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= 402 | 403 | delayed-stream@~1.0.0: 404 | version "1.0.0" 405 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 406 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 407 | 408 | diff@5.0.0: 409 | version "5.0.0" 410 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 411 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 412 | 413 | doctrine@^3.0.0: 414 | version "3.0.0" 415 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" 416 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 417 | dependencies: 418 | esutils "^2.0.2" 419 | 420 | domexception@^2.0.1: 421 | version "2.0.1" 422 | resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" 423 | integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== 424 | dependencies: 425 | webidl-conversions "^5.0.0" 426 | 427 | emoji-regex@^8.0.0: 428 | version "8.0.0" 429 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 430 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 431 | 432 | enquirer@^2.3.5: 433 | version "2.3.6" 434 | resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" 435 | integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== 436 | dependencies: 437 | ansi-colors "^4.1.1" 438 | 439 | escalade@^3.1.1: 440 | version "3.1.1" 441 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 442 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 443 | 444 | escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: 445 | version "4.0.0" 446 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 447 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 448 | 449 | escape-string-regexp@^1.0.5: 450 | version "1.0.5" 451 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 452 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 453 | 454 | escodegen@^2.0.0: 455 | version "2.0.0" 456 | resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" 457 | integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== 458 | dependencies: 459 | esprima "^4.0.1" 460 | estraverse "^5.2.0" 461 | esutils "^2.0.2" 462 | optionator "^0.8.1" 463 | optionalDependencies: 464 | source-map "~0.6.1" 465 | 466 | eslint-scope@^5.1.1: 467 | version "5.1.1" 468 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" 469 | integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 470 | dependencies: 471 | esrecurse "^4.3.0" 472 | estraverse "^4.1.1" 473 | 474 | eslint-utils@^2.1.0: 475 | version "2.1.0" 476 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" 477 | integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== 478 | dependencies: 479 | eslint-visitor-keys "^1.1.0" 480 | 481 | eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: 482 | version "1.3.0" 483 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" 484 | integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== 485 | 486 | eslint-visitor-keys@^2.0.0: 487 | version "2.1.0" 488 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" 489 | integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== 490 | 491 | eslint@7: 492 | version "7.28.0" 493 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.28.0.tgz#435aa17a0b82c13bb2be9d51408b617e49c1e820" 494 | integrity sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g== 495 | dependencies: 496 | "@babel/code-frame" "7.12.11" 497 | "@eslint/eslintrc" "^0.4.2" 498 | ajv "^6.10.0" 499 | chalk "^4.0.0" 500 | cross-spawn "^7.0.2" 501 | debug "^4.0.1" 502 | doctrine "^3.0.0" 503 | enquirer "^2.3.5" 504 | escape-string-regexp "^4.0.0" 505 | eslint-scope "^5.1.1" 506 | eslint-utils "^2.1.0" 507 | eslint-visitor-keys "^2.0.0" 508 | espree "^7.3.1" 509 | esquery "^1.4.0" 510 | esutils "^2.0.2" 511 | fast-deep-equal "^3.1.3" 512 | file-entry-cache "^6.0.1" 513 | functional-red-black-tree "^1.0.1" 514 | glob-parent "^5.1.2" 515 | globals "^13.6.0" 516 | ignore "^4.0.6" 517 | import-fresh "^3.0.0" 518 | imurmurhash "^0.1.4" 519 | is-glob "^4.0.0" 520 | js-yaml "^3.13.1" 521 | json-stable-stringify-without-jsonify "^1.0.1" 522 | levn "^0.4.1" 523 | lodash.merge "^4.6.2" 524 | minimatch "^3.0.4" 525 | natural-compare "^1.4.0" 526 | optionator "^0.9.1" 527 | progress "^2.0.0" 528 | regexpp "^3.1.0" 529 | semver "^7.2.1" 530 | strip-ansi "^6.0.0" 531 | strip-json-comments "^3.1.0" 532 | table "^6.0.9" 533 | text-table "^0.2.0" 534 | v8-compile-cache "^2.0.3" 535 | 536 | espree@^7.3.0, espree@^7.3.1: 537 | version "7.3.1" 538 | resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" 539 | integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== 540 | dependencies: 541 | acorn "^7.4.0" 542 | acorn-jsx "^5.3.1" 543 | eslint-visitor-keys "^1.3.0" 544 | 545 | esprima@^4.0.0, esprima@^4.0.1: 546 | version "4.0.1" 547 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 548 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 549 | 550 | esquery@^1.4.0: 551 | version "1.4.0" 552 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" 553 | integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== 554 | dependencies: 555 | estraverse "^5.1.0" 556 | 557 | esrecurse@^4.3.0: 558 | version "4.3.0" 559 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 560 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 561 | dependencies: 562 | estraverse "^5.2.0" 563 | 564 | estraverse@^4.1.1: 565 | version "4.3.0" 566 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 567 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 568 | 569 | estraverse@^5.1.0, estraverse@^5.2.0: 570 | version "5.2.0" 571 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" 572 | integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== 573 | 574 | esutils@^2.0.2: 575 | version "2.0.3" 576 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 577 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 578 | 579 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 580 | version "3.1.3" 581 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 582 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 583 | 584 | fast-json-stable-stringify@^2.0.0: 585 | version "2.1.0" 586 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 587 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 588 | 589 | fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: 590 | version "2.0.6" 591 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 592 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 593 | 594 | file-entry-cache@^6.0.1: 595 | version "6.0.1" 596 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" 597 | integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== 598 | dependencies: 599 | flat-cache "^3.0.4" 600 | 601 | fill-range@^7.0.1: 602 | version "7.0.1" 603 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 604 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 605 | dependencies: 606 | to-regex-range "^5.0.1" 607 | 608 | find-up@5.0.0: 609 | version "5.0.0" 610 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 611 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 612 | dependencies: 613 | locate-path "^6.0.0" 614 | path-exists "^4.0.0" 615 | 616 | flat-cache@^3.0.4: 617 | version "3.0.4" 618 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" 619 | integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== 620 | dependencies: 621 | flatted "^3.1.0" 622 | rimraf "^3.0.2" 623 | 624 | flat@^5.0.2: 625 | version "5.0.2" 626 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 627 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 628 | 629 | flatted@^3.1.0: 630 | version "3.1.1" 631 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" 632 | integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== 633 | 634 | form-data@^3.0.0: 635 | version "3.0.1" 636 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" 637 | integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== 638 | dependencies: 639 | asynckit "^0.4.0" 640 | combined-stream "^1.0.8" 641 | mime-types "^2.1.12" 642 | 643 | fs.realpath@^1.0.0: 644 | version "1.0.0" 645 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 646 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 647 | 648 | fsevents@~2.3.1: 649 | version "2.3.2" 650 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 651 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 652 | 653 | functional-red-black-tree@^1.0.1: 654 | version "1.0.1" 655 | resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" 656 | integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= 657 | 658 | get-caller-file@^2.0.5: 659 | version "2.0.5" 660 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 661 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 662 | 663 | glob-parent@^5.1.2, glob-parent@~5.1.0: 664 | version "5.1.2" 665 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 666 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 667 | dependencies: 668 | is-glob "^4.0.1" 669 | 670 | glob@7.1.7, glob@^7.1.3: 671 | version "7.1.7" 672 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" 673 | integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== 674 | dependencies: 675 | fs.realpath "^1.0.0" 676 | inflight "^1.0.4" 677 | inherits "2" 678 | minimatch "^3.0.4" 679 | once "^1.3.0" 680 | path-is-absolute "^1.0.0" 681 | 682 | globals@^13.6.0, globals@^13.9.0: 683 | version "13.9.0" 684 | resolved "https://registry.yarnpkg.com/globals/-/globals-13.9.0.tgz#4bf2bf635b334a173fb1daf7c5e6b218ecdc06cb" 685 | integrity sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA== 686 | dependencies: 687 | type-fest "^0.20.2" 688 | 689 | growl@1.10.5: 690 | version "1.10.5" 691 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" 692 | integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== 693 | 694 | has-flag@^3.0.0: 695 | version "3.0.0" 696 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 697 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 698 | 699 | has-flag@^4.0.0: 700 | version "4.0.0" 701 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 702 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 703 | 704 | he@1.2.0: 705 | version "1.2.0" 706 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 707 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 708 | 709 | html-encoding-sniffer@^2.0.1: 710 | version "2.0.1" 711 | resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" 712 | integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== 713 | dependencies: 714 | whatwg-encoding "^1.0.5" 715 | 716 | http-proxy-agent@^4.0.1: 717 | version "4.0.1" 718 | resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" 719 | integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== 720 | dependencies: 721 | "@tootallnate/once" "1" 722 | agent-base "6" 723 | debug "4" 724 | 725 | https-proxy-agent@^5.0.0: 726 | version "5.0.0" 727 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" 728 | integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== 729 | dependencies: 730 | agent-base "6" 731 | debug "4" 732 | 733 | iconv-lite@0.4.24: 734 | version "0.4.24" 735 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 736 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 737 | dependencies: 738 | safer-buffer ">= 2.1.2 < 3" 739 | 740 | ignore@^4.0.6: 741 | version "4.0.6" 742 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" 743 | integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== 744 | 745 | import-fresh@^3.0.0, import-fresh@^3.2.1: 746 | version "3.3.0" 747 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" 748 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 749 | dependencies: 750 | parent-module "^1.0.0" 751 | resolve-from "^4.0.0" 752 | 753 | imurmurhash@^0.1.4: 754 | version "0.1.4" 755 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 756 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 757 | 758 | inflight@^1.0.4: 759 | version "1.0.6" 760 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 761 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 762 | dependencies: 763 | once "^1.3.0" 764 | wrappy "1" 765 | 766 | inherits@2: 767 | version "2.0.4" 768 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 769 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 770 | 771 | is-binary-path@~2.1.0: 772 | version "2.1.0" 773 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 774 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 775 | dependencies: 776 | binary-extensions "^2.0.0" 777 | 778 | is-extglob@^2.1.1: 779 | version "2.1.1" 780 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 781 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 782 | 783 | is-fullwidth-code-point@^2.0.0: 784 | version "2.0.0" 785 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 786 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 787 | 788 | is-fullwidth-code-point@^3.0.0: 789 | version "3.0.0" 790 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 791 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 792 | 793 | is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: 794 | version "4.0.1" 795 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 796 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 797 | dependencies: 798 | is-extglob "^2.1.1" 799 | 800 | is-number@^7.0.0: 801 | version "7.0.0" 802 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 803 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 804 | 805 | is-plain-obj@^2.1.0: 806 | version "2.1.0" 807 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 808 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 809 | 810 | is-potential-custom-element-name@^1.0.1: 811 | version "1.0.1" 812 | resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" 813 | integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== 814 | 815 | is-unicode-supported@^0.1.0: 816 | version "0.1.0" 817 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 818 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 819 | 820 | isexe@^2.0.0: 821 | version "2.0.0" 822 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 823 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 824 | 825 | jest-worker@^26.2.1: 826 | version "26.6.2" 827 | resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" 828 | integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== 829 | dependencies: 830 | "@types/node" "*" 831 | merge-stream "^2.0.0" 832 | supports-color "^7.0.0" 833 | 834 | js-tokens@^4.0.0: 835 | version "4.0.0" 836 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 837 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 838 | 839 | js-yaml@4.1.0: 840 | version "4.1.0" 841 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 842 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 843 | dependencies: 844 | argparse "^2.0.1" 845 | 846 | js-yaml@^3.13.1: 847 | version "3.14.1" 848 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" 849 | integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== 850 | dependencies: 851 | argparse "^1.0.7" 852 | esprima "^4.0.0" 853 | 854 | jsdom@16: 855 | version "16.6.0" 856 | resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.6.0.tgz#f79b3786682065492a3da6a60a4695da983805ac" 857 | integrity sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg== 858 | dependencies: 859 | abab "^2.0.5" 860 | acorn "^8.2.4" 861 | acorn-globals "^6.0.0" 862 | cssom "^0.4.4" 863 | cssstyle "^2.3.0" 864 | data-urls "^2.0.0" 865 | decimal.js "^10.2.1" 866 | domexception "^2.0.1" 867 | escodegen "^2.0.0" 868 | form-data "^3.0.0" 869 | html-encoding-sniffer "^2.0.1" 870 | http-proxy-agent "^4.0.1" 871 | https-proxy-agent "^5.0.0" 872 | is-potential-custom-element-name "^1.0.1" 873 | nwsapi "^2.2.0" 874 | parse5 "6.0.1" 875 | saxes "^5.0.1" 876 | symbol-tree "^3.2.4" 877 | tough-cookie "^4.0.0" 878 | w3c-hr-time "^1.0.2" 879 | w3c-xmlserializer "^2.0.0" 880 | webidl-conversions "^6.1.0" 881 | whatwg-encoding "^1.0.5" 882 | whatwg-mimetype "^2.3.0" 883 | whatwg-url "^8.5.0" 884 | ws "^7.4.5" 885 | xml-name-validator "^3.0.0" 886 | 887 | json-schema-traverse@^0.4.1: 888 | version "0.4.1" 889 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 890 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 891 | 892 | json-schema-traverse@^1.0.0: 893 | version "1.0.0" 894 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" 895 | integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== 896 | 897 | json-stable-stringify-without-jsonify@^1.0.1: 898 | version "1.0.1" 899 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 900 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= 901 | 902 | levn@^0.4.1: 903 | version "0.4.1" 904 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" 905 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 906 | dependencies: 907 | prelude-ls "^1.2.1" 908 | type-check "~0.4.0" 909 | 910 | levn@~0.3.0: 911 | version "0.3.0" 912 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" 913 | integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= 914 | dependencies: 915 | prelude-ls "~1.1.2" 916 | type-check "~0.3.2" 917 | 918 | locate-path@^6.0.0: 919 | version "6.0.0" 920 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 921 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 922 | dependencies: 923 | p-locate "^5.0.0" 924 | 925 | lodash.clonedeep@^4.5.0: 926 | version "4.5.0" 927 | resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" 928 | integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= 929 | 930 | lodash.merge@^4.6.2: 931 | version "4.6.2" 932 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" 933 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 934 | 935 | lodash.truncate@^4.4.2: 936 | version "4.4.2" 937 | resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" 938 | integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= 939 | 940 | lodash@^4.7.0: 941 | version "4.17.21" 942 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 943 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 944 | 945 | log-symbols@4.1.0: 946 | version "4.1.0" 947 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 948 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 949 | dependencies: 950 | chalk "^4.1.0" 951 | is-unicode-supported "^0.1.0" 952 | 953 | lru-cache@^6.0.0: 954 | version "6.0.0" 955 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 956 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 957 | dependencies: 958 | yallist "^4.0.0" 959 | 960 | merge-stream@^2.0.0: 961 | version "2.0.0" 962 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 963 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 964 | 965 | mime-db@1.48.0: 966 | version "1.48.0" 967 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" 968 | integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== 969 | 970 | mime-types@^2.1.12: 971 | version "2.1.31" 972 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" 973 | integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== 974 | dependencies: 975 | mime-db "1.48.0" 976 | 977 | minimatch@3.0.4, minimatch@^3.0.4: 978 | version "3.0.4" 979 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 980 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 981 | dependencies: 982 | brace-expansion "^1.1.7" 983 | 984 | mocha@9: 985 | version "9.0.0" 986 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.0.0.tgz#67ce848170cb6426f9e84c57e38376dc9017bab4" 987 | integrity sha512-GRGG/q9bIaUkHJB9NL+KZNjDhMBHB30zW3bZW9qOiYr+QChyLjPzswaxFWkI1q6lGlSL28EQYzAi2vKWNkPx+g== 988 | dependencies: 989 | "@ungap/promise-all-settled" "1.1.2" 990 | ansi-colors "4.1.1" 991 | browser-stdout "1.3.1" 992 | chokidar "3.5.1" 993 | debug "4.3.1" 994 | diff "5.0.0" 995 | escape-string-regexp "4.0.0" 996 | find-up "5.0.0" 997 | glob "7.1.7" 998 | growl "1.10.5" 999 | he "1.2.0" 1000 | js-yaml "4.1.0" 1001 | log-symbols "4.1.0" 1002 | minimatch "3.0.4" 1003 | ms "2.1.3" 1004 | nanoid "3.1.23" 1005 | serialize-javascript "5.0.1" 1006 | strip-json-comments "3.1.1" 1007 | supports-color "8.1.1" 1008 | which "2.0.2" 1009 | wide-align "1.1.3" 1010 | workerpool "6.1.4" 1011 | yargs "16.2.0" 1012 | yargs-parser "20.2.4" 1013 | yargs-unparser "2.0.0" 1014 | 1015 | ms@2.1.2: 1016 | version "2.1.2" 1017 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1018 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1019 | 1020 | ms@2.1.3: 1021 | version "2.1.3" 1022 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1023 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1024 | 1025 | nanoid@3.1.23: 1026 | version "3.1.23" 1027 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" 1028 | integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== 1029 | 1030 | natural-compare@^1.4.0: 1031 | version "1.4.0" 1032 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 1033 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= 1034 | 1035 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1036 | version "3.0.0" 1037 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 1038 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1039 | 1040 | nwsapi@^2.2.0: 1041 | version "2.2.0" 1042 | resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" 1043 | integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== 1044 | 1045 | once@^1.3.0: 1046 | version "1.4.0" 1047 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1048 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 1049 | dependencies: 1050 | wrappy "1" 1051 | 1052 | optionator@^0.8.1: 1053 | version "0.8.3" 1054 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" 1055 | integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== 1056 | dependencies: 1057 | deep-is "~0.1.3" 1058 | fast-levenshtein "~2.0.6" 1059 | levn "~0.3.0" 1060 | prelude-ls "~1.1.2" 1061 | type-check "~0.3.2" 1062 | word-wrap "~1.2.3" 1063 | 1064 | optionator@^0.9.1: 1065 | version "0.9.1" 1066 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" 1067 | integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== 1068 | dependencies: 1069 | deep-is "^0.1.3" 1070 | fast-levenshtein "^2.0.6" 1071 | levn "^0.4.1" 1072 | prelude-ls "^1.2.1" 1073 | type-check "^0.4.0" 1074 | word-wrap "^1.2.3" 1075 | 1076 | p-limit@^3.0.2: 1077 | version "3.1.0" 1078 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 1079 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1080 | dependencies: 1081 | yocto-queue "^0.1.0" 1082 | 1083 | p-locate@^5.0.0: 1084 | version "5.0.0" 1085 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1086 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1087 | dependencies: 1088 | p-limit "^3.0.2" 1089 | 1090 | parent-module@^1.0.0: 1091 | version "1.0.1" 1092 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 1093 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1094 | dependencies: 1095 | callsites "^3.0.0" 1096 | 1097 | parse5@6.0.1: 1098 | version "6.0.1" 1099 | resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" 1100 | integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== 1101 | 1102 | path-exists@^4.0.0: 1103 | version "4.0.0" 1104 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1105 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1106 | 1107 | path-is-absolute@^1.0.0: 1108 | version "1.0.1" 1109 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1110 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1111 | 1112 | path-key@^3.1.0: 1113 | version "3.1.1" 1114 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1115 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1116 | 1117 | picomatch@^2.0.4, picomatch@^2.2.1: 1118 | version "2.3.0" 1119 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" 1120 | integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== 1121 | 1122 | prelude-ls@^1.2.1: 1123 | version "1.2.1" 1124 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" 1125 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 1126 | 1127 | prelude-ls@~1.1.2: 1128 | version "1.1.2" 1129 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 1130 | integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= 1131 | 1132 | progress@^2.0.0: 1133 | version "2.0.3" 1134 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" 1135 | integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== 1136 | 1137 | psl@^1.1.33: 1138 | version "1.8.0" 1139 | resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" 1140 | integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== 1141 | 1142 | punycode@^2.1.0, punycode@^2.1.1: 1143 | version "2.1.1" 1144 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 1145 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 1146 | 1147 | randombytes@^2.1.0: 1148 | version "2.1.0" 1149 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 1150 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 1151 | dependencies: 1152 | safe-buffer "^5.1.0" 1153 | 1154 | readdirp@~3.5.0: 1155 | version "3.5.0" 1156 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" 1157 | integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== 1158 | dependencies: 1159 | picomatch "^2.2.1" 1160 | 1161 | regexpp@^3.1.0: 1162 | version "3.1.0" 1163 | resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" 1164 | integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== 1165 | 1166 | require-directory@^2.1.1: 1167 | version "2.1.1" 1168 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1169 | integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= 1170 | 1171 | require-from-string@^2.0.2: 1172 | version "2.0.2" 1173 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" 1174 | integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 1175 | 1176 | resolve-from@^4.0.0: 1177 | version "4.0.0" 1178 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1179 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1180 | 1181 | rimraf@^3.0.2: 1182 | version "3.0.2" 1183 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1184 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1185 | dependencies: 1186 | glob "^7.1.3" 1187 | 1188 | rollup-plugin-terser@7: 1189 | version "7.0.2" 1190 | resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" 1191 | integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== 1192 | dependencies: 1193 | "@babel/code-frame" "^7.10.4" 1194 | jest-worker "^26.2.1" 1195 | serialize-javascript "^4.0.0" 1196 | terser "^5.0.0" 1197 | 1198 | rollup@2: 1199 | version "2.51.1" 1200 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.51.1.tgz#87bcd4095fe79b14c9bec0edc7ffa44e4827f793" 1201 | integrity sha512-8xfDbAtBleXotb6qKEHWuo/jkn94a9dVqGc7Rwl3sqspCVlnCfbRek7ldhCARSi7h32H0xR4QThm1t9zHN+3uw== 1202 | optionalDependencies: 1203 | fsevents "~2.3.1" 1204 | 1205 | safe-buffer@^5.1.0: 1206 | version "5.2.1" 1207 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1208 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1209 | 1210 | "safer-buffer@>= 2.1.2 < 3": 1211 | version "2.1.2" 1212 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1213 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1214 | 1215 | saxes@^5.0.1: 1216 | version "5.0.1" 1217 | resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" 1218 | integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== 1219 | dependencies: 1220 | xmlchars "^2.2.0" 1221 | 1222 | semver@^7.2.1: 1223 | version "7.3.5" 1224 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" 1225 | integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== 1226 | dependencies: 1227 | lru-cache "^6.0.0" 1228 | 1229 | serialize-javascript@5.0.1: 1230 | version "5.0.1" 1231 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" 1232 | integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== 1233 | dependencies: 1234 | randombytes "^2.1.0" 1235 | 1236 | serialize-javascript@^4.0.0: 1237 | version "4.0.0" 1238 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" 1239 | integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== 1240 | dependencies: 1241 | randombytes "^2.1.0" 1242 | 1243 | shebang-command@^2.0.0: 1244 | version "2.0.0" 1245 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1246 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1247 | dependencies: 1248 | shebang-regex "^3.0.0" 1249 | 1250 | shebang-regex@^3.0.0: 1251 | version "3.0.0" 1252 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1253 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1254 | 1255 | slice-ansi@^4.0.0: 1256 | version "4.0.0" 1257 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" 1258 | integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== 1259 | dependencies: 1260 | ansi-styles "^4.0.0" 1261 | astral-regex "^2.0.0" 1262 | is-fullwidth-code-point "^3.0.0" 1263 | 1264 | source-map-support@~0.5.19: 1265 | version "0.5.19" 1266 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" 1267 | integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== 1268 | dependencies: 1269 | buffer-from "^1.0.0" 1270 | source-map "^0.6.0" 1271 | 1272 | source-map@^0.6.0, source-map@~0.6.1: 1273 | version "0.6.1" 1274 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1275 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1276 | 1277 | source-map@~0.7.2: 1278 | version "0.7.3" 1279 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" 1280 | integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== 1281 | 1282 | sprintf-js@~1.0.2: 1283 | version "1.0.3" 1284 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1285 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 1286 | 1287 | "string-width@^1.0.2 || 2": 1288 | version "2.1.1" 1289 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 1290 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 1291 | dependencies: 1292 | is-fullwidth-code-point "^2.0.0" 1293 | strip-ansi "^4.0.0" 1294 | 1295 | string-width@^4.1.0, string-width@^4.2.0: 1296 | version "4.2.2" 1297 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" 1298 | integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== 1299 | dependencies: 1300 | emoji-regex "^8.0.0" 1301 | is-fullwidth-code-point "^3.0.0" 1302 | strip-ansi "^6.0.0" 1303 | 1304 | strip-ansi@^4.0.0: 1305 | version "4.0.0" 1306 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 1307 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 1308 | dependencies: 1309 | ansi-regex "^3.0.0" 1310 | 1311 | strip-ansi@^6.0.0: 1312 | version "6.0.0" 1313 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" 1314 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== 1315 | dependencies: 1316 | ansi-regex "^5.0.0" 1317 | 1318 | strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: 1319 | version "3.1.1" 1320 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1321 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1322 | 1323 | supports-color@8.1.1: 1324 | version "8.1.1" 1325 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 1326 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 1327 | dependencies: 1328 | has-flag "^4.0.0" 1329 | 1330 | supports-color@^5.3.0: 1331 | version "5.5.0" 1332 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1333 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1334 | dependencies: 1335 | has-flag "^3.0.0" 1336 | 1337 | supports-color@^7.0.0, supports-color@^7.1.0: 1338 | version "7.2.0" 1339 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1340 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1341 | dependencies: 1342 | has-flag "^4.0.0" 1343 | 1344 | symbol-tree@^3.2.4: 1345 | version "3.2.4" 1346 | resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" 1347 | integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== 1348 | 1349 | table@^6.0.9: 1350 | version "6.7.1" 1351 | resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" 1352 | integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== 1353 | dependencies: 1354 | ajv "^8.0.1" 1355 | lodash.clonedeep "^4.5.0" 1356 | lodash.truncate "^4.4.2" 1357 | slice-ansi "^4.0.0" 1358 | string-width "^4.2.0" 1359 | strip-ansi "^6.0.0" 1360 | 1361 | terser@^5.0.0: 1362 | version "5.7.0" 1363 | resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.0.tgz#a761eeec206bc87b605ab13029876ead938ae693" 1364 | integrity sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g== 1365 | dependencies: 1366 | commander "^2.20.0" 1367 | source-map "~0.7.2" 1368 | source-map-support "~0.5.19" 1369 | 1370 | text-table@^0.2.0: 1371 | version "0.2.0" 1372 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 1373 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 1374 | 1375 | to-regex-range@^5.0.1: 1376 | version "5.0.1" 1377 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1378 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1379 | dependencies: 1380 | is-number "^7.0.0" 1381 | 1382 | tough-cookie@^4.0.0: 1383 | version "4.0.0" 1384 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" 1385 | integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== 1386 | dependencies: 1387 | psl "^1.1.33" 1388 | punycode "^2.1.1" 1389 | universalify "^0.1.2" 1390 | 1391 | tr46@^2.1.0: 1392 | version "2.1.0" 1393 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" 1394 | integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== 1395 | dependencies: 1396 | punycode "^2.1.1" 1397 | 1398 | type-check@^0.4.0, type-check@~0.4.0: 1399 | version "0.4.0" 1400 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" 1401 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 1402 | dependencies: 1403 | prelude-ls "^1.2.1" 1404 | 1405 | type-check@~0.3.2: 1406 | version "0.3.2" 1407 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 1408 | integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= 1409 | dependencies: 1410 | prelude-ls "~1.1.2" 1411 | 1412 | type-fest@^0.20.2: 1413 | version "0.20.2" 1414 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" 1415 | integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 1416 | 1417 | universalify@^0.1.2: 1418 | version "0.1.2" 1419 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" 1420 | integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== 1421 | 1422 | uri-js@^4.2.2: 1423 | version "4.4.1" 1424 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1425 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1426 | dependencies: 1427 | punycode "^2.1.0" 1428 | 1429 | v8-compile-cache@^2.0.3: 1430 | version "2.3.0" 1431 | resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" 1432 | integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== 1433 | 1434 | w3c-hr-time@^1.0.2: 1435 | version "1.0.2" 1436 | resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" 1437 | integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== 1438 | dependencies: 1439 | browser-process-hrtime "^1.0.0" 1440 | 1441 | w3c-xmlserializer@^2.0.0: 1442 | version "2.0.0" 1443 | resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" 1444 | integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== 1445 | dependencies: 1446 | xml-name-validator "^3.0.0" 1447 | 1448 | webidl-conversions@^5.0.0: 1449 | version "5.0.0" 1450 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" 1451 | integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== 1452 | 1453 | webidl-conversions@^6.1.0: 1454 | version "6.1.0" 1455 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" 1456 | integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== 1457 | 1458 | whatwg-encoding@^1.0.5: 1459 | version "1.0.5" 1460 | resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" 1461 | integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== 1462 | dependencies: 1463 | iconv-lite "0.4.24" 1464 | 1465 | whatwg-mimetype@^2.3.0: 1466 | version "2.3.0" 1467 | resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" 1468 | integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== 1469 | 1470 | whatwg-url@^8.0.0, whatwg-url@^8.5.0: 1471 | version "8.6.0" 1472 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.6.0.tgz#27c0205a4902084b872aecb97cf0f2a7a3011f4c" 1473 | integrity sha512-os0KkeeqUOl7ccdDT1qqUcS4KH4tcBTSKK5Nl5WKb2lyxInIZ/CpjkqKa1Ss12mjfdcRX9mHmPPs7/SxG1Hbdw== 1474 | dependencies: 1475 | lodash "^4.7.0" 1476 | tr46 "^2.1.0" 1477 | webidl-conversions "^6.1.0" 1478 | 1479 | which@2.0.2, which@^2.0.1: 1480 | version "2.0.2" 1481 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1482 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1483 | dependencies: 1484 | isexe "^2.0.0" 1485 | 1486 | wide-align@1.1.3: 1487 | version "1.1.3" 1488 | resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" 1489 | integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== 1490 | dependencies: 1491 | string-width "^1.0.2 || 2" 1492 | 1493 | word-wrap@^1.2.3, word-wrap@~1.2.3: 1494 | version "1.2.3" 1495 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" 1496 | integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== 1497 | 1498 | workerpool@6.1.4: 1499 | version "6.1.4" 1500 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.4.tgz#6a972b6df82e38d50248ee2820aa98e2d0ad3090" 1501 | integrity sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g== 1502 | 1503 | wrap-ansi@^7.0.0: 1504 | version "7.0.0" 1505 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1506 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1507 | dependencies: 1508 | ansi-styles "^4.0.0" 1509 | string-width "^4.1.0" 1510 | strip-ansi "^6.0.0" 1511 | 1512 | wrappy@1: 1513 | version "1.0.2" 1514 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1515 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1516 | 1517 | ws@^7.4.5: 1518 | version "7.4.6" 1519 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" 1520 | integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== 1521 | 1522 | xml-name-validator@^3.0.0: 1523 | version "3.0.0" 1524 | resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" 1525 | integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== 1526 | 1527 | xmlchars@^2.2.0: 1528 | version "2.2.0" 1529 | resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" 1530 | integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== 1531 | 1532 | y18n@^5.0.5: 1533 | version "5.0.8" 1534 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 1535 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 1536 | 1537 | yallist@^4.0.0: 1538 | version "4.0.0" 1539 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 1540 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1541 | 1542 | yargs-parser@20.2.4: 1543 | version "20.2.4" 1544 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 1545 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 1546 | 1547 | yargs-parser@^20.2.2: 1548 | version "20.2.7" 1549 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a" 1550 | integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw== 1551 | 1552 | yargs-unparser@2.0.0: 1553 | version "2.0.0" 1554 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 1555 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 1556 | dependencies: 1557 | camelcase "^6.0.0" 1558 | decamelize "^4.0.0" 1559 | flat "^5.0.2" 1560 | is-plain-obj "^2.1.0" 1561 | 1562 | yargs@16.2.0: 1563 | version "16.2.0" 1564 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 1565 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 1566 | dependencies: 1567 | cliui "^7.0.2" 1568 | escalade "^3.1.1" 1569 | get-caller-file "^2.0.5" 1570 | require-directory "^2.1.1" 1571 | string-width "^4.2.0" 1572 | y18n "^5.0.5" 1573 | yargs-parser "^20.2.2" 1574 | 1575 | yocto-queue@^0.1.0: 1576 | version "0.1.0" 1577 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1578 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1579 | --------------------------------------------------------------------------------