From 6c0bec9b49fb4b51e37f886b6bb98fea7c1424f0 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Thu, 26 Sep 2024 00:35:05 -0400 Subject: [PATCH 01/30] update plugin-corsi-blocks to v8 --- package-lock.json | 2439 ++++++++++++----- .../plugin-corsi-blocks/examples/example.html | 4 +- packages/plugin-corsi-blocks/package.json | 6 +- packages/plugin-corsi-blocks/src/index.ts | 25 + 4 files changed, 1839 insertions(+), 635 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0a97c4a4..cc1a3cbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2326,6 +2326,38 @@ "integrity": "sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==", "dev": true }, + "node_modules/@esbuild/android-arm": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.14.tgz", + "integrity": "sha512-+Rb20XXxRGisNu2WmNKk+scpanb7nL5yhuI1KR9wQFiC43ddPj/V1fmNyzlFC9bKiG4mYzxW7egtoHVcynr+OA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.14.tgz", + "integrity": "sha512-eQi9rosGNVQFJyJWV0HCA5WZae/qWIQME7s8/j8DMvnylfBv62Pbu+zJ2eUDqNf2O4u3WB+OEXyfkpBoe194sg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@gulpjs/messages": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", @@ -3967,6 +3999,48 @@ "node": ">= 0.10" } }, + "node_modules/@jspsych/config/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/@jspsych/config/node_modules/rollup/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/@jspsych/config/node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -4002,6 +4076,19 @@ "node": ">= 0.10" } }, + "node_modules/@jspsych/config/node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@jspsych/config/node_modules/undertaker": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", @@ -7793,6 +7880,12 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, "node_modules/es-object-atoms": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", @@ -7897,636 +7990,695 @@ "es6-symbol": "^3.1.1" } }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "node_modules/esbuild": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.14.tgz", + "integrity": "sha512-pJN8j42fvWLFWwSMG4luuupl2Me7mxciUOsMegKvwCmhEbJ2covUdFnihxm0FMIBV+cbwbtMoHgMCCI+pj1btQ==", "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, + "hasInstallScript": true, "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=6.0" + "node": ">=12" }, "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "@esbuild/android-arm": "0.15.14", + "@esbuild/linux-loong64": "0.15.14", + "esbuild-android-64": "0.15.14", + "esbuild-android-arm64": "0.15.14", + "esbuild-darwin-64": "0.15.14", + "esbuild-darwin-arm64": "0.15.14", + "esbuild-freebsd-64": "0.15.14", + "esbuild-freebsd-arm64": "0.15.14", + "esbuild-linux-32": "0.15.14", + "esbuild-linux-64": "0.15.14", + "esbuild-linux-arm": "0.15.14", + "esbuild-linux-arm64": "0.15.14", + "esbuild-linux-mips64le": "0.15.14", + "esbuild-linux-ppc64le": "0.15.14", + "esbuild-linux-riscv64": "0.15.14", + "esbuild-linux-s390x": "0.15.14", + "esbuild-netbsd-64": "0.15.14", + "esbuild-openbsd-64": "0.15.14", + "esbuild-sunos-64": "0.15.14", + "esbuild-windows-32": "0.15.14", + "esbuild-windows-64": "0.15.14", + "esbuild-windows-arm64": "0.15.14" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.14.tgz", + "integrity": "sha512-HuilVIb4rk9abT4U6bcFdU35UHOzcWVGLSjEmC58OVr96q5UiRqzDtWjPlCMugjhgUGKEs8Zf4ueIvYbOStbIg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=0.10" + "node": ">=12" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/esbuild-android-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.14.tgz", + "integrity": "sha512-/QnxRVxsR2Vtf3XottAHj7hENAMW2wCs6S+OZcAbc/8nlhbAL/bCQRCVD78VtI5mdwqWkVi3wMqM94kScQCgqg==", + "cpu": [ + "arm64" + ], "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/esbuild-darwin-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.14.tgz", + "integrity": "sha512-ToNuf1uifu8hhwWvoZJGCdLIX/1zpo8cOGnT0XAhDQXiKOKYaotVNx7pOVB1f+wHoWwTLInrOmh3EmA7Fd+8Vg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=4.0" + "node": ">=12" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.14.tgz", + "integrity": "sha512-KgGP+y77GszfYJgceO0Wi/PiRtYo5y2Xo9rhBUpxTPaBgWDJ14gqYN0+NMbu+qC2fykxXaipHxN4Scaj9tUS1A==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/eve": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/eve/-/eve-0.5.4.tgz", - "integrity": "sha512-aqprQ9MAOh1t66PrHxDFmMXPlgNO6Uv1uqvxmwjprQV50jaQ2RqO7O1neY4PJwC+hMnkyMDphu2AQPOPZdjQog==" - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "node_modules/esbuild-freebsd-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.14.tgz", + "integrity": "sha512-xr0E2n5lyWw3uFSwwUXHc0EcaBDtsal/iIfLioflHdhAe10KSctV978Te7YsfnsMKzcoGeS366+tqbCXdqDHQA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.14.tgz", + "integrity": "sha512-8XH96sOQ4b1LhMlO10eEWOjEngmZ2oyw3pW4o8kvBcpF6pULr56eeYVP5radtgw54g3T8nKHDHYEI5AItvskZg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=12" } }, - "node_modules/execa/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/esbuild-linux-32": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.14.tgz", + "integrity": "sha512-6ssnvwaTAi8AzKN8By2V0nS+WF5jTP7SfuK6sStGnDP7MCJo/4zHgM9oE1eQTS2jPmo3D673rckuCzRlig+HMA==", + "cpu": [ + "ia32" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/esbuild-linux-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.14.tgz", + "integrity": "sha512-ONySx3U0wAJOJuxGUlXBWxVKFVpWv88JEv0NZ6NlHknmDd1yCbf4AEdClSgLrqKQDXYywmw4gYDvdLsS6z0hcw==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.8.0" + "node": ">=12" } }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.14.tgz", + "integrity": "sha512-D2LImAIV3QzL7lHURyCHBkycVFbKwkDb1XEUWan+2fb4qfW7qAeUtul7ZIcIwFKZgPcl+6gKZmvLgPSj26RQ2Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/esbuild-linux-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.14.tgz", + "integrity": "sha512-kle2Ov6a1e5AjlHlMQl1e+c4myGTeggrRzArQFmWp6O6JoqqB9hT+B28EW4tjFWgV/NxUq46pWYpgaWXsXRPAg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ms": "2.0.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.14.tgz", + "integrity": "sha512-FVdMYIzOLXUq+OE7XYKesuEAqZhmAIV6qOoYahvUp93oXy0MOVTP370ECbPfGXXUdlvc0TNgkJa3YhEwyZ6MRA==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.14.tgz", + "integrity": "sha512-2NzH+iuzMDA+jjtPjuIz/OhRDf8tzbQ1tRZJI//aT25o1HKc0reMMXxKIYq/8nSHXiJSnYV4ODzTiv45s+h73w==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.14.tgz", + "integrity": "sha512-VqxvutZNlQxmUNS7Ac+aczttLEoHBJ9e3OYGqnULrfipRvG97qLrAv9EUY9iSrRKBqeEbSvS9bSfstZqwz0T4Q==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "node_modules/esbuild-linux-s390x": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.14.tgz", + "integrity": "sha512-+KVHEUshX5n6VP6Vp/AKv9fZIl5kr2ph8EUFmQUJnDpHwcfTSn2AQgYYm0HTBR2Mr4d0Wlr0FxF/Cs5pbFgiOw==", + "cpu": [ + "s390x" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "node_modules/esbuild-netbsd-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.14.tgz", + "integrity": "sha512-6D/dr17piEgevIm1xJfZP2SjB9Z+g8ERhNnBdlZPBWZl+KSPUKLGF13AbvC+nzGh8IxOH2TyTIdRMvKMP0nEzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.14.tgz", + "integrity": "sha512-rREQBIlMibBetgr2E9Lywt2Qxv2ZdpmYahR4IUlAQ1Efv/A5gYdO0/VIN3iowDbCNTLxp0bb57Vf0LFcffD6kA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/esbuild-sunos-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.14.tgz", + "integrity": "sha512-DNVjSp/BY4IfwtdUAvWGIDaIjJXY5KI4uD82+15v6k/w7px9dnaDaJJ2R6Mu+KCgr5oklmFc0KjBjh311Gxl9Q==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "node_modules/esbuild-windows-32": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.14.tgz", + "integrity": "sha512-pHBWrcA+/oLgvViuG9FO3kNPO635gkoVrRQwe6ZY1S0jdET07xe2toUvQoJQ8KT3/OkxqUasIty5hpuKFLD+eg==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "type": "^2.7.2" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "node_modules/esbuild-windows-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.14.tgz", + "integrity": "sha512-CszIGQVk/P8FOS5UgAH4hKc9zOaFo69fe+k1rqgBHx3CSK3Opyk5lwYriIamaWOVjBt7IwEP6NALz+tkVWdFog==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "node_modules/esbuild-windows-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.14.tgz", + "integrity": "sha512-KW9W4psdZceaS9A7Jsgl4WialOznSURvqX/oHZk3gOP7KbjtHLSsnmSvNdzagGJfxbAe30UVGXRe8q8nDsOSQw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/extendable-error": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", - "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", - "dev": true + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=4" + "node": ">=0.8.0" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", "dev": true, "dependencies": { - "is-descriptor": "^1.0.0" + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, "engines": { - "node": ">=8.6.0" + "node": ">=4.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, - "node_modules/fast-levenshtein": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", - "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", - "dependencies": { - "fastest-levenshtein": "^1.0.7" - } - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { - "node": ">= 4.9.1" + "node": ">=0.10.0" } }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dependencies": { - "reusify": "^1.0.4" - } + "node_modules/eve": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/eve/-/eve-0.5.4.tgz", + "integrity": "sha512-aqprQ9MAOh1t66PrHxDFmMXPlgNO6Uv1uqvxmwjprQV50jaQ2RqO7O1neY4PJwC+hMnkyMDphu2AQPOPZdjQog==" }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "dev": true, "dependencies": { - "bser": "2.1.1" + "d": "1", + "es5-ext": "~0.10.14" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.5" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, - "optional": true + "engines": { + "node": ">= 0.8.0" + } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" + "ms": "2.0.0" } }, - "node_modules/find-cache-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "is-descriptor": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "dependencies": { - "p-limit": "^2.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/find-cache-dir/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir/node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", "dependencies": { - "find-up": "^3.0.0" + "homedir-polyfill": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/find-line-column": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/find-line-column/-/find-line-column-0.5.2.tgz", - "integrity": "sha512-eNhNkDt5RbxY4X++JwyDURP62FYhV1bh9LF4dfOiwpVCTk5vvfEANhnui5ypUEELGR02QZSrWFtaTgd4ulW5tw==", - "dev": true - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/find-yarn-workspace-root2": { - "version": "1.2.16", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", - "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==", + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "dev": true, "dependencies": { - "micromatch": "^4.0.2", - "pkg-dir": "^4.2.0" + "type": "^2.7.2" } }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, + "node_modules/extendable-error": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", + "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", + "dev": true + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "dependencies": { - "is-extendable": "^0.1.0" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "dev": true, "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "is-descriptor": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow": { + "node_modules/extglob/node_modules/extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", @@ -8538,7 +8690,7 @@ "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/is-extendable": { + "node_modules/extglob/node_modules/is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", @@ -8547,265 +8699,563 @@ "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", "dev": true, "dependencies": { - "kind-of": "^3.0.2" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/findup-sync/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { - "is-buffer": "^1.1.5" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6.0" } }, - "node_modules/findup-sync/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, - "node_modules/findup-sync/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, + "node_modules/fast-levenshtein": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", + "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, + "fastest-levenshtein": "^1.0.7" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "engines": { - "node": ">=0.10.0" + "node": ">= 4.9.1" } }, - "node_modules/findup-sync/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" + "reusify": "^1.0.4" } }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" + "bser": "2.1.1" } }, - "node_modules/fined/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/flow-parser": { - "version": "0.237.2", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.237.2.tgz", - "integrity": "sha512-mvI/kdfr3l1waaPbThPA8dJa77nHXrfZIun+SWvFwSwDjmeByU7mGJGRmv1+7guU6ccyLV8e1lqZA1lD4iMGnQ==", + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=6" } }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, "dependencies": { - "for-in": "^1.0.1" + "p-limit": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "node_modules/find-cache-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "find-up": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": ">=6" } }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "node_modules/find-line-column": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/find-line-column/-/find-line-column-0.5.2.tgz", + "integrity": "sha512-eNhNkDt5RbxY4X++JwyDURP62FYhV1bh9LF4dfOiwpVCTk5vvfEANhnui5ypUEELGR02QZSrWFtaTgd4ulW5tw==", + "dev": true + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "map-cache": "^0.2.2" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "node_modules/find-yarn-workspace-root2": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", + "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "micromatch": "^4.0.2", + "pkg-dir": "^4.2.0" + } + }, + "node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">= 0.10" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/findup-sync/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, "dependencies": { - "minipass": "^3.0.0" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/fs-minipass/node_modules/yallist": { + "node_modules/findup-sync/node_modules/fill-range": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/fs-mkdirp-stream": { + "node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", - "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, "dependencies": { - "graceful-fs": "^4.2.8", - "streamx": "^2.12.0" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=0.10.0" } }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "node_modules/findup-sync/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/findup-sync/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=0.10.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", + "node_modules/findup-sync/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flow-parser": { + "version": "0.237.2", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.237.2.tgz", + "integrity": "sha512-mvI/kdfr3l1waaPbThPA8dJa77nHXrfZIun+SWvFwSwDjmeByU7mGJGRmv1+7guU6ccyLV8e1lqZA1lD4iMGnQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/fs-mkdirp-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", + "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", + "dependencies": { + "graceful-fs": "^4.2.8", + "streamx": "^2.12.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "funding": { @@ -12765,6 +13215,15 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -13124,6 +13583,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -15703,33 +16168,89 @@ } }, "node_modules/rollup": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", - "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, + "peer": true, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=18.0.0", + "node": ">=14.18.0", "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.3.0", - "@rollup/rollup-android-arm64": "4.3.0", - "@rollup/rollup-darwin-arm64": "4.3.0", - "@rollup/rollup-darwin-x64": "4.3.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", - "@rollup/rollup-linux-arm64-gnu": "4.3.0", - "@rollup/rollup-linux-arm64-musl": "4.3.0", - "@rollup/rollup-linux-x64-gnu": "4.3.0", - "@rollup/rollup-linux-x64-musl": "4.3.0", - "@rollup/rollup-win32-arm64-msvc": "4.3.0", - "@rollup/rollup-win32-ia32-msvc": "4.3.0", - "@rollup/rollup-win32-x64-msvc": "4.3.0", "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-dts": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-5.0.0.tgz", + "integrity": "sha512-OO8ayCvuJCKaQSShyVTARxGurVVk4ulzbuvz+0zFd1f93vlnWFU5pBMT7HFeS6uj7MvvZLx4kUAarGATSU1+Ng==", + "dev": true, + "dependencies": { + "magic-string": "^0.26.7" + }, + "engines": { + "node": ">=v14" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.18.6" + }, + "peerDependencies": { + "rollup": "^3.0.0", + "typescript": "^4.1" + } + }, + "node_modules/rollup-plugin-dts/node_modules/magic-string": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", + "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/rollup-plugin-esbuild": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-5.0.0.tgz", + "integrity": "sha512-1cRIOHAPh8WQgdQQyyvFdeOdxuiyk+zB5zJ5+YOwrZP4cJ0MT3Fs48pQxrZeyZHcn+klFherytILVfE4aYrneg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "debug": "^4.3.4", + "es-module-lexer": "^1.0.5", + "joycon": "^3.1.1", + "jsonc-parser": "^3.2.0" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.10.1", + "rollup": "^1.20.0 || ^2.0.0 || ^3.0.0" + } + }, + "node_modules/rollup-plugin-node-externals": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-externals/-/rollup-plugin-node-externals-5.0.2.tgz", + "integrity": "sha512-UGAPdPjD0PPk4hNcHLnqwqsfNc/u0vaAjWnjkyS6j2jIMB4LLi1pW3TE01eaytJKZactNik2t8AQC33esS9GKw==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.60.0 || ^3.0.0" + } + }, "node_modules/rollup-plugin-typescript2": { "version": "0.36.0", "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.36.0.tgz", @@ -16580,6 +17101,13 @@ "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true + }, "node_modules/sparkles": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", @@ -17726,16 +18254,17 @@ "dev": true }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, "node_modules/unbox-primitive": { @@ -18825,12 +19354,662 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.3.2" + "jspsych": "^8.0.0" }, "peerDependencies": { - "jspsych": ">=7.3.2" + "jspsych": ">=8.0.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-corsi-blocks/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-corsi-blocks/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-corsi-blocks/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-corsi-blocks/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-corsi-blocks/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-corsi-blocks/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-corsi-blocks/node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-corsi-blocks/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-corsi-blocks/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-corsi-blocks/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-gamepad": { diff --git a/packages/plugin-corsi-blocks/examples/example.html b/packages/plugin-corsi-blocks/examples/example.html index 8fe0bc58..4fcb9dbd 100644 --- a/packages/plugin-corsi-blocks/examples/example.html +++ b/packages/plugin-corsi-blocks/examples/example.html @@ -1,9 +1,9 @@ - + - + + - - - + + + @@ -68,34 +68,35 @@ {'values': [100, 100, 50, 90]}, {'values': [100, 100, 50, 90]}, {'values': [100, 50, 200, 90]}, - {'values': [50, 50, 50, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 50, 50, 90]}, - {'values': [50, 50, 50, 90]}, - {'values': [100, 50, 200, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 50, 200, 90]}, - {'values': [50, 50, 50, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 50, 50, 90]}, - {'values': [50, 50, 50, 90]}, - {'values': [100, 50, 200, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 50, 200, 90]}, - {'values': [50, 50, 50, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 50, 50, 90]}, - {'values': [50, 50, 50, 90]}, - {'values': [100, 50, 200, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 50, 200, 90]}, - {'values': [50, 50, 50, 90]}, - {'values': [100, 100, 50, 90]}, - {'values': [100, 50, 50, 90]}, - {'values': [50, 50, 50, 90]},] + {'values': [50, 50, 50, 90]}, // truncated for simplicity, uncomment values to get full experience + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 50, 50, 90]}, + // {'values': [50, 50, 50, 90]}, + // {'values': [100, 50, 200, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 50, 200, 90]}, + // {'values': [50, 50, 50, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 50, 50, 90]}, + // {'values': [50, 50, 50, 90]}, + // {'values': [100, 50, 200, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 50, 200, 90]}, + // {'values': [50, 50, 50, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 50, 50, 90]}, + // {'values': [50, 50, 50, 90]}, + // {'values': [100, 50, 200, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 50, 200, 90]}, + // {'values': [50, 50, 50, 90]}, + // {'values': [100, 100, 50, 90]}, + // {'values': [100, 50, 50, 90]}, + // {'values': [50, 50, 50, 90]}, + ] } timeline.push(test) diff --git a/packages/plugin-html-choice/package.json b/packages/plugin-html-choice/package.json index fbbd2946..5c4e2dfd 100644 --- a/packages/plugin-html-choice/package.json +++ b/packages/plugin-html-choice/package.json @@ -37,11 +37,11 @@ }, "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-html-choice", "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" } } diff --git a/packages/plugin-html-choice/src/index.ts b/packages/plugin-html-choice/src/index.ts index a66fd002..e3b240dc 100644 --- a/packages/plugin-html-choice/src/index.ts +++ b/packages/plugin-html-choice/src/index.ts @@ -2,12 +2,14 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; const info = { name: "html-choice", + version: "2.0.0", parameters: { /** The HTML string to be displayed */ html_array: { type: ParameterType.HTML_STRING, pretty_name: "Stimulus", - default: undefined, + default: [], + array: true, }, /** How long to show the stimulus. */ stimulus_duration: { @@ -40,6 +42,26 @@ const info = { default: 0, }, }, + data: { + /** The response time in milliseconds for the participant to make a response. The time is measured from + * when the stimulus first appears on the screen until the participant makes a response. */ + rt: { + type: ParameterType.INT, + }, + /** The HTML stimulus displayed. */ + stimulus: { + type: ParameterType.HTML_STRING, + array: true, + }, + /** The index of the HTML stimulus chosen */ + choice: { + type: ParameterType.INT, + }, + /** The value associated with the stimulus that was chosen. */ + value: { + type: ParameterType.INT, + }, + }, }; type Info = typeof info; @@ -62,7 +84,7 @@ class HtmlChoicePlugin implements JsPsychPlugin { } else if (trial.values.length === trial.html_array.length) { values = trial.values; } else { - throw new Error("array of html-choices does not have the same length as array of valuse"); + throw new Error("array of html-choices does not have the same length as array of values"); } // display stimulus var html = "
"; From b143a7b24cf40fe662ecf756efde1506e13f44b0 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Sun, 29 Sep 2024 20:15:06 -0400 Subject: [PATCH 03/30] updated plugin-ios to v8 --- package-lock.json | 654 +++++++++++++++++++++- packages/plugin-ios/README.md | 2 +- packages/plugin-ios/examples/classic.html | 12 +- packages/plugin-ios/examples/group.html | 10 +- packages/plugin-ios/index.js | 341 +++++++---- packages/plugin-ios/package.json | 4 +- 6 files changed, 888 insertions(+), 135 deletions(-) diff --git a/package-lock.json b/package-lock.json index e6b90a78..2725f2fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20800,8 +20800,658 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@jspsych/config": "^2.0.0", - "jspsych": "^7.0.0" + "@jspsych/config": "^3.0.0", + "jspsych": "^8.0.0" + } + }, + "packages/plugin-ios/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-ios/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-ios/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-ios/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-ios/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-ios/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-ios/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-ios/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-ios/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-ios/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-ios/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-ios/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-ios/node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-ios/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-ios/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-ios/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-libet-intentional-binding": { diff --git a/packages/plugin-ios/README.md b/packages/plugin-ios/README.md index 6591c46c..d76844bd 100644 --- a/packages/plugin-ios/README.md +++ b/packages/plugin-ios/README.md @@ -12,7 +12,7 @@ This plugin allows for continuous responses on the Inclusion of Other in the Sel ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For using jsPsych v7.0, use version 1.0.0. ## Documentation diff --git a/packages/plugin-ios/examples/classic.html b/packages/plugin-ios/examples/classic.html index a404efe0..672a2c71 100644 --- a/packages/plugin-ios/examples/classic.html +++ b/packages/plugin-ios/examples/classic.html @@ -1,17 +1,17 @@ - - - - - + + + + + - - - + + + + + - - - - - - - - - + + + + + + + + + + + + + - - - + + + + - + + - + + + diff --git a/packages/plugin-gamepad/examples/minature-gamepad.html b/packages/plugin-gamepad/examples/minature-gamepad.html index 092e38cd..4bba9c63 100644 --- a/packages/plugin-gamepad/examples/minature-gamepad.html +++ b/packages/plugin-gamepad/examples/minature-gamepad.html @@ -4,8 +4,8 @@ jspsych-gamepad plugin test - - + + diff --git a/packages/plugin-gamepad/examples/move-a-ball.html b/packages/plugin-gamepad/examples/move-a-ball.html index 65bf7875..366ff760 100644 --- a/packages/plugin-gamepad/examples/move-a-ball.html +++ b/packages/plugin-gamepad/examples/move-a-ball.html @@ -4,8 +4,8 @@ jspsych-gamepad plugin test - - + + diff --git a/packages/plugin-gamepad/examples/vibration.html b/packages/plugin-gamepad/examples/vibration.html index f769036e..de9842e0 100644 --- a/packages/plugin-gamepad/examples/vibration.html +++ b/packages/plugin-gamepad/examples/vibration.html @@ -4,8 +4,8 @@ jspsych-gamepad plugin test - - + + diff --git a/packages/plugin-gamepad/src/index.ts b/packages/plugin-gamepad/src/index.ts index b47f3162..79a1395f 100644 --- a/packages/plugin-gamepad/src/index.ts +++ b/packages/plugin-gamepad/src/index.ts @@ -4,10 +4,9 @@ import { GamepadModel, GamepadModels } from "./gamepad-model"; const info = { name: "gamepad", + version: "2.0.0", parameters: { - /** - * The size of the canvas element - */ + /** The size of the canvas element. */ canvas_size: { type: ParameterType.INT, default: [500, 500], @@ -80,6 +79,18 @@ const info = { default: (_context: CanvasRenderingContext2D) => {}, }, }, + data: { + /** The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first + * began playing until the participant's response. + */ + rt: { + type: ParameterType.INT, + }, + /** The gamepad inputs recorded during the trial. */ + input: { + type: ParameterType.COMPLEX, + }, + }, }; type Info = typeof info; From aae3d13838fbca65cb1eeda714b982b43cae650c Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Tue, 1 Oct 2024 21:39:43 -0400 Subject: [PATCH 08/30] update plugin-nextcloud-firedrop to v8 --- packages/plugin-nextcloud-filedrop/README.md | 4 ++-- .../example/plugin-nextcloud-filedrop.html | 6 +++--- packages/plugin-nextcloud-filedrop/index.js | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/plugin-nextcloud-filedrop/README.md b/packages/plugin-nextcloud-filedrop/README.md index b921adad..7c793dfe 100644 --- a/packages/plugin-nextcloud-filedrop/README.md +++ b/packages/plugin-nextcloud-filedrop/README.md @@ -63,7 +63,7 @@ Files with the same filename will automatically be enumerated. ### Trial Parameters -This plulgin accepts the following parameters +This plugin accepts the following parameters: ```js @@ -75,7 +75,7 @@ var trial = { folder: 'Z6oaSWW9W9edmyk', filename: null, generate_download_url_on_error: true - }); + }; ``` Parameter | Type | Default Value | Description diff --git a/packages/plugin-nextcloud-filedrop/example/plugin-nextcloud-filedrop.html b/packages/plugin-nextcloud-filedrop/example/plugin-nextcloud-filedrop.html index 0d9f8f81..39131fb7 100644 --- a/packages/plugin-nextcloud-filedrop/example/plugin-nextcloud-filedrop.html +++ b/packages/plugin-nextcloud-filedrop/example/plugin-nextcloud-filedrop.html @@ -2,11 +2,11 @@ - - + + - + diff --git a/packages/plugin-nextcloud-filedrop/index.js b/packages/plugin-nextcloud-filedrop/index.js index 21853259..753be9ea 100644 --- a/packages/plugin-nextcloud-filedrop/index.js +++ b/packages/plugin-nextcloud-filedrop/index.js @@ -3,6 +3,7 @@ var jsPsychNextcloudFiledropPlugin = (function (jspsych) { const info = { name: "nextcloud-upload", + version: "2.0.0", parameters: { url: { type: jspsych.ParameterType.STRING, @@ -21,6 +22,20 @@ var jsPsychNextcloudFiledropPlugin = (function (jspsych) { default: false, }, }, + data: { + /** The name of the uploaded file. */ + filename: { + type: jspsych.ParameterType.STRING, + }, + /** Whether an error occurred during upload. */ + error: { + type: jspsych.ParameterType.BOOL, + }, + /** The URL to download the file in case of an error. */ + url: { + type: jspsych.ParameterType.STRING, + }, + }, }; /** From 2b358194e3a51d5de37155a6ed7a6ff3b5311d32 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Wed, 2 Oct 2024 05:28:50 -0400 Subject: [PATCH 09/30] update plugin-html-keyboard-response-raf to v8 --- .../README.md | 2 +- .../examples/example1.html | 4 ++-- .../src/index.ts | 21 ++++++++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/plugin-html-keyboard-response-raf/README.md b/packages/plugin-html-keyboard-response-raf/README.md index 24fc6bd8..8f3faa15 100644 --- a/packages/plugin-html-keyboard-response-raf/README.md +++ b/packages/plugin-html-keyboard-response-raf/README.md @@ -2,7 +2,7 @@ ## Overview -This plugin implements the same functionality as the html-keyboard-response plugin, but uses requestAnimationFrame internally for timing +This plugin implements the same functionality as the html-keyboard-response plugin, but uses requestAnimationFrame internally for timing. ## Loading diff --git a/packages/plugin-html-keyboard-response-raf/examples/example1.html b/packages/plugin-html-keyboard-response-raf/examples/example1.html index 476adad0..3e4126cb 100644 --- a/packages/plugin-html-keyboard-response-raf/examples/example1.html +++ b/packages/plugin-html-keyboard-response-raf/examples/example1.html @@ -1,9 +1,9 @@ - + - + + - - - + + + + - + diff --git a/packages/plugin-image-multi-response/package.json b/packages/plugin-image-multi-response/package.json index b02d591a..4ded543c 100644 --- a/packages/plugin-image-multi-response/package.json +++ b/packages/plugin-image-multi-response/package.json @@ -37,11 +37,11 @@ }, "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-image-multi-response", "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" } } diff --git a/packages/plugin-image-multi-response/src/index.spec.ts b/packages/plugin-image-multi-response/src/index.spec.ts index bc2c6a3b..088daa25 100644 --- a/packages/plugin-image-multi-response/src/index.spec.ts +++ b/packages/plugin-image-multi-response/src/index.spec.ts @@ -53,12 +53,15 @@ describe("plugin-image-multi-response", () => { }); test("display button html", async () => { + const buttonHtmlFn = jest.fn(); + buttonHtmlFn.mockReturnValue(""); + const { getHTML } = await startTimeline([ { type: imageMultiResponse, stimulus: "../media/blue.png", button_choices: ["buttonChoice"], - button_html: '', + button_html: buttonHtmlFn, }, ]); diff --git a/packages/plugin-image-multi-response/src/index.ts b/packages/plugin-image-multi-response/src/index.ts index cecf3e84..974c3d48 100644 --- a/packages/plugin-image-multi-response/src/index.ts +++ b/packages/plugin-image-multi-response/src/index.ts @@ -2,6 +2,7 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; const info = { name: "image-multi-response", + version: "2.0.0", parameters: { /** The image to be displayed */ stimulus: { @@ -34,20 +35,24 @@ const info = { default: [], array: true, }, - /** - * Array containing the key(s) the subject is allowed to press to respond to the stimulus. - */ + /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */ keyboard_choices: { type: ParameterType.KEYS, pretty_name: "Keyboard Choices", default: "NO_KEYS", }, - /** The HTML for creating button. Can create own style. Use the "%choice%" string to indicate where the label from the choices parameter should be inserted. */ + /** + * A function that generates the HTML for each button in the `choices` array. + * The function gets the string and index of the item in the `choices` array and should return valid HTML. + * If you want to use different markup for each button, you can do that by using a conditional on either parameter. + * The default parameter returns a button element with the text label of the choice. + */ button_html: { - type: ParameterType.HTML_STRING, + type: ParameterType.FUNCTION, pretty_name: "Button HTML", - default: '', - array: true, + default: function (choice: string, choice_index: number) { + return ``; + }, }, /** Any content here will be displayed under the button(s). */ prompt: { @@ -95,6 +100,37 @@ const info = { default: true, }, }, + data: { + /** + * The response time in milliseconds for the participant to make a response. + * The time is measured from when the stimulus first appears on the screen until the participant's response. + */ + rt: { + type: ParameterType.INT, + }, + /** The HTML content that was displayed on the screen. */ + stimulus: { + type: ParameterType.STRING, + }, + /** + * Indicates which button the subject pressed. The first button in the `choices` array is 0, the second is 1, and so on. + * If the subject responded using the keyboard, then this field will be `null`. + */ + button_response: { + type: ParameterType.INT, + }, + /** + * Indicates which key the subject pressed. + * If the subject responded using button clicks, then this field will be `null`. + */ + keyboard_response: { + type: ParameterType.STRING, + }, + /** Indicates the source of the response. This will either be `"button"` or `"keyboard"`. */ + response_source: { + type: ParameterType.STRING, + }, + }, }; type Info = typeof info; @@ -111,8 +147,8 @@ class ImageMultiResponsePlugin implements JsPsychPlugin { constructor(private jsPsych: JsPsych) {} trial(display_element: HTMLElement, trial: TrialType) { - var height, width; - var html; + var height: number, width: number; + var html: string; if (trial.render_on_canvas) { var image_drawn = false; // first clear the display element (because the render_on_canvas method appends to display_element instead of overwriting it with .innerHTML) @@ -161,26 +197,13 @@ class ImageMultiResponsePlugin implements JsPsychPlugin { canvas.width = width; }; getHeightWidth(); // call now, in case image loads immediately (is cached) - // create buttons - var buttons = []; - if (Array.isArray(trial.button_html)) { - if (trial.button_html.length == trial.button_choices.length) { - buttons = trial.button_html; - } else { - console.error( - "Error in image-multi-response plugin. The length of the button_html array does not equal the length of the button_choices array" - ); - } - } else { - for (var i = 0; i < trial.button_choices.length; i++) { - buttons.push(trial.button_html); - } - } + var btngroup_div = document.createElement("div"); btngroup_div.id = "jspsych-image-multi-response-btngroup"; html = ""; for (var i = 0; i < trial.button_choices.length; i++) { - var str = buttons[i].replace(/%choice%/g, trial.button_choices[i]); + var button_str = trial.button_html(trial.button_choices[i], i); + html += '
' + - str + + button_str + "
"; } btngroup_div.innerHTML = html; @@ -215,25 +238,11 @@ class ImageMultiResponsePlugin implements JsPsychPlugin { ''; - //display buttons - var buttons = []; - if (Array.isArray(trial.button_html)) { - if (trial.button_html.length == trial.button_choices.length) { - buttons = trial.button_html; - } else { - console.error( - "Error in image-multi-response plugin. The length of the button_html array does not equal the length of the button_choices array" - ); - } - } else { - for (var i = 0; i < trial.button_choices.length; i++) { - buttons.push(trial.button_html); - } - } + html += '
'; for (var i = 0; i < trial.button_choices.length; i++) { - var str = buttons[i].replace(/%choice%/g, trial.button_choices[i]); + var button_str = trial.button_html(trial.button_choices[i], i); html += '
' + - str + + button_str + "
"; } html += "
"; @@ -354,15 +363,12 @@ class ImageMultiResponsePlugin implements JsPsychPlugin { response_source: response.source, }; - // clear the display - display_element.innerHTML = ""; - // move on to the next trial this.jsPsych.finishTrial(trial_data); }; // function to handle responses by the subject - function after_response(choice) { + function after_response(choice: string) { // measure rt var end_time = performance.now(); var rt = Math.round(end_time - start_time); From 7f83e8aa10d36202dba23158b3dd3c2bb176dc63 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Thu, 10 Oct 2024 22:55:05 -0400 Subject: [PATCH 12/30] update plugin-image-array-keyboard-response to v8 --- package-lock.json | 656 +++++++++++++++++- .../jspsych-image-array-keyboard-response.md | 4 +- .../examples/example1.html | 15 +- .../package.json | 6 +- .../src/index.ts | 35 +- 5 files changed, 692 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16896024..d47c7819 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20758,12 +20758,662 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" }, "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-image-array-keyboard-response/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-image-array-keyboard-response/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-image-array-keyboard-response/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-image-multi-response": { diff --git a/packages/plugin-image-array-keyboard-response/docs/jspsych-image-array-keyboard-response.md b/packages/plugin-image-array-keyboard-response/docs/jspsych-image-array-keyboard-response.md index 7a6b29cd..df3b75f7 100644 --- a/packages/plugin-image-array-keyboard-response/docs/jspsych-image-array-keyboard-response.md +++ b/packages/plugin-image-array-keyboard-response/docs/jspsych-image-array-keyboard-response.md @@ -10,7 +10,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org | Parameter | Type | Default Value | Description | |-----------------------------|------------------| ------------------ |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | stimulus | array of string | *undefined* | The path of the image files to be displayed. | -| stimulus_rect | array of integer | null | Set the positionX, positionY, witdh, height of the images in pixels. If left null for width and height (no value specified), then the image will display at its natural height. | +| stimulus_rect | array of integer | null | Set the positionX, positionY, width, and height of the images in pixels. If width and height are left null, then the image will display at its natural height. | | maintain_aspect_ratio | boolean | true | If setting *only* the width or *only* the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. | | choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the subject is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. | @@ -34,7 +34,7 @@ In addition to the [default data collected by all plugins](../overview/plugins.m let trial = { type: jsPsychImageArrayKeyboardResponse, stimulus: ['./img/dot_green.png', './img/dot_yellow.png'], - stimulus_rect: [[1000,100,200, 50],[0, 100, null, 100]], + stimulus_rect: [[1000, 100, 200, 50],[0, 100, null, 100]], choices: ['f'], correct_choice: ['f'], trial_duration: 4000, diff --git a/packages/plugin-image-array-keyboard-response/examples/example1.html b/packages/plugin-image-array-keyboard-response/examples/example1.html index beec4bed..36f37d4e 100644 --- a/packages/plugin-image-array-keyboard-response/examples/example1.html +++ b/packages/plugin-image-array-keyboard-response/examples/example1.html @@ -1,10 +1,10 @@ - + - - + + @@ -26,14 +26,11 @@ // push the preload trial into the timeline timeline.push(preload); - - // make a rok-trials - // minimal example -- let trial = { - type: jsPsychImageArrayKeyboardResponse, // plugin type to tell jsPsych witch trial-type to use + type: jsPsychImageArrayKeyboardResponse, stimulus: ['./img/dot_green.png', './img/dot_yellow.png'], - stimulus_rect: [[1000,100,200, 50],[0, 100, null, 100]], // if null, then aspect ratio is preserved + stimulus_rect: [[1000, 100, 200, 50],[0, 100, null, 100]], // if null, then aspect ratio is preserved choices: ['f'], // valid key presses correct_choice: ['f'], // correct key press trial_duration: 4000, // duration of stimulus presentation, 0 for infinite (valid key press ends the trial) @@ -42,7 +39,7 @@ }; timeline.push(trial); - //---------Run the experiment--------- + //---------Run the experiment--------- jsPsych.run(timeline); diff --git a/packages/plugin-image-array-keyboard-response/package.json b/packages/plugin-image-array-keyboard-response/package.json index 59e0ed95..1baf1f81 100644 --- a/packages/plugin-image-array-keyboard-response/package.json +++ b/packages/plugin-image-array-keyboard-response/package.json @@ -37,11 +37,11 @@ }, "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-image-array-keyboard-response", "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" } } diff --git a/packages/plugin-image-array-keyboard-response/src/index.ts b/packages/plugin-image-array-keyboard-response/src/index.ts index 804697bd..bd3b5b44 100644 --- a/packages/plugin-image-array-keyboard-response/src/index.ts +++ b/packages/plugin-image-array-keyboard-response/src/index.ts @@ -2,18 +2,22 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; const info = { name: "image-array-keyboard-response", + version: "2.0.0", parameters: { - /** The image to be displayed */ + /** The images to be displayed */ stimulus: { type: ParameterType.IMAGE, pretty_name: "Stimulus", - default: undefined, + array: true, }, - /** Set the image rectangle in pixels */ + /** + * Set the image rectangle in pixels, each array in the form of [positionX, positionY, width, height]. + * If width and height are left null, then the image will display at its natural height. + */ stimulus_rect: { - type: ParameterType.INT, + type: ParameterType.COMPLEX, pretty_name: "Image rectangle", - default: null, + array: true, }, /** Maintain the aspect ratio after setting width or height */ maintain_aspect_ratio: { @@ -55,6 +59,22 @@ const info = { default: true, }, }, + data: { + /** The response time in milliseconds for the participant to make a response. + * The time is measured from when the stimulus first appears on the screen until the participant's response. */ + rt: { + type: ParameterType.INT, + }, + /** The paths to the stimuli shown in the trial. */ + stimulus: { + type: ParameterType.STRING, + array: true, + }, + /** The key that the subject pressed. */ + response: { + type: ParameterType.STRING, + }, + }, }; type Info = typeof info; @@ -73,7 +93,7 @@ class ImageArrayKeyboardResponsePlugin implements JsPsychPlugin { constructor(private jsPsych: JsPsych) {} trial(display_element: HTMLElement, trial: TrialType) { - let height, width; + let height: number, width: number; if (trial.render_on_canvas) { let image_drawn = []; // first clear the display element (because the render_on_canvas method appends to display_element instead of overwriting it with .innerHTML) @@ -83,8 +103,8 @@ class ImageArrayKeyboardResponsePlugin implements JsPsychPlugin { display_element.removeChild(display_element.firstChild); } } - // create canvas element and image + // create canvas element and image let canvas = document.createElement("canvas"); canvas.id = "jspsych-image-keyboard-response-stimulus"; canvas.style.margin = "0"; @@ -104,6 +124,7 @@ class ImageArrayKeyboardResponsePlugin implements JsPsychPlugin { } }; img.src = trial.stimulus[i]; + // get/set image height and width - this can only be done after image loads because uses image's naturalWidth/naturalHeight properties const getHeightWidth = () => { const stimulus_height = trial.stimulus_rect[i][3]; From 299b2a4edc039eb78eca90b1ea48bc94136d0901 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Thu, 10 Oct 2024 23:16:21 -0400 Subject: [PATCH 13/30] update plugin-html-vas-response to v8 --- package-lock.json | 654 +++++++++++++++++- .../docs/jspsych-html-vas-response.md | 4 +- .../plugin-html-vas-response/examples/expt.js | 2 +- .../examples/html-vas-response.js | 275 -------- .../examples/index.html | 7 +- packages/plugin-html-vas-response/index.js | 63 +- .../plugin-html-vas-response/package.json | 4 +- 7 files changed, 719 insertions(+), 290 deletions(-) delete mode 100644 packages/plugin-html-vas-response/examples/html-vas-response.js diff --git a/package-lock.json b/package-lock.json index d47c7819..e42a557e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20749,8 +20749,658 @@ "version": "1.2.0", "license": "MIT", "devDependencies": { - "@jspsych/config": "^2.0.0", - "jspsych": "^7.0.0" + "@jspsych/config": "^3.0.0", + "jspsych": "^8.0.0" + } + }, + "packages/plugin-html-vas-response/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-html-vas-response/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-html-vas-response/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-html-vas-response/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-html-vas-response/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-html-vas-response/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-html-vas-response/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-html-vas-response/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-html-vas-response/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-html-vas-response/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-html-vas-response/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-html-vas-response/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-html-vas-response/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-vas-response/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-vas-response/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-image-array-keyboard-response": { diff --git a/packages/plugin-html-vas-response/docs/jspsych-html-vas-response.md b/packages/plugin-html-vas-response/docs/jspsych-html-vas-response.md index 0fefe1c1..6a65ce89 100644 --- a/packages/plugin-html-vas-response/docs/jspsych-html-vas-response.md +++ b/packages/plugin-html-vas-response/docs/jspsych-html-vas-response.md @@ -16,8 +16,8 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org | labels | array of strings | `[]` | Specifies the labels to be displayed, equally spaced along the scale, as in jspsych-html-slider-response. | | resp_fcn | function | `null` | A function called when the participant clicks on the scale. The current location of the participant's response (between 0 and 1) is provided as an input. | | ticks | Boolean | `true` | Specifies whether smaller vertical tick marks should accompany the labels. | -| n_scale_points | integer | `null` | If the scale should have some set of discrete clickable points (such that the tick mark will be rounded to the nearest such point), this parameter can be used specify the number of such points. | -| scale_width | integer | `null` | The width of the VAS in pixels. If left null, then the width will be equal to the widest element in the display. | +| n_scale_points | integer | `null` | If the scale should have some set of discrete clickable points (such that the tick mark will be rounded to the nearest such point), this parameter can be used specify the number of such points. If not, set this to `null`. | +| scale_width | integer | `null` | The width of the VAS in pixels. If left `null`, then the width will be equal to the widest element in the display. | | scale_height | integer | 40 | The height of the clickable region around the VAS in pixels. | | scale_colour | string | `'black'` | The colour of the scale (the horizontal line). Anything that would make a valid CSS `background` property can be used here; e.g., `'linear-gradient(to right, blue, red)'` | | scale_cursor | string | `'pointer'` | The style of the cursor when the clickable part of the scale is hovered over. | diff --git a/packages/plugin-html-vas-response/examples/expt.js b/packages/plugin-html-vas-response/examples/expt.js index 0924629c..09a43b41 100644 --- a/packages/plugin-html-vas-response/examples/expt.js +++ b/packages/plugin-html-vas-response/examples/expt.js @@ -1,6 +1,6 @@ var jsPsych = initJsPsych({ on_finish: function () { - jsPsych.data.displayData("csv"); + jsPsych.data.displayData(); }, }); diff --git a/packages/plugin-html-vas-response/examples/html-vas-response.js b/packages/plugin-html-vas-response/examples/html-vas-response.js deleted file mode 100644 index 3c307c51..00000000 --- a/packages/plugin-html-vas-response/examples/html-vas-response.js +++ /dev/null @@ -1,275 +0,0 @@ -var jsPsychHtmlVasResponse = (function (jspsych) { - "use strict"; - - const info = { - name: "html-vas-response", - parameters: { - stimulus: { - type: jspsych.ParameterType.HTML_STRING, - pretty_name: "Stimulus", - default: undefined, - }, - labels: { - type: jspsych.ParameterType.HTML_STRING, - pretty_name: "Labels", - default: [], - array: true, - }, - resp_fcn: { - type: jspsych.ParameterType.FUNCTION, - pretty_name: "Response function", - default: null, - }, - ticks: { - type: jspsych.ParameterType.BOOL, - pretty_name: "Ticks", - default: true, - }, - n_scale_points: { - type: jspsych.ParameterType.BOOL, - pretty_name: "Number of scale points", - default: false, - }, - scale_width: { - type: jspsych.ParameterType.INT, - pretty_name: "VAS width", - default: null, - }, - scale_height: { - type: jspsych.ParameterType.INT, - pretty_name: "VAS height", - default: 40, - }, - scale_colour: { - type: jspsych.ParameterType.STRING, - pretty_name: "Scale colour", - default: "black", - }, - scale_cursor: { - type: jspsych.ParameterType.STRING, - pretty_name: "Scale cursor", - default: "pointer", - }, - marker_colour: { - type: jspsych.ParameterType.STRING, - pretty_name: "Marker colour", - default: "rgba(0, 0, 0, 0.5)", - }, - tick_colour: { - type: jspsych.ParameterType.STRING, - pretty_name: "tick colour", - default: "black", - }, - prompt: { - type: jspsych.ParameterType.HTML_STRING, - pretty_name: "Prompt", - default: null, - }, - button_label: { - type: jspsych.ParameterType.HTML_STRING, - pretty_name: "Buton label", - default: "Continue", - }, - required: { - type: jspsych.ParameterType.BOOL, - pretty_name: "Response required", - default: false, - }, - stimulus_duration: { - type: jspsych.ParameterType.INT, - pretty_name: "Stimulus duration", - default: null, - }, - trial_duration: { - type: jspsych.ParameterType.INT, - pretty_name: "Trial duration", - default: null, - }, - response_ends_trial: { - type: jspsych.ParameterType.BOOL, - pretty_name: "Response ends trial", - default: true, - }, - }, - }; - class jsPsychHtmlVasResponsePlugin { - constructor(jsPsych) { - this.jsPsych = jsPsych; - } - trial(display_element, trial) { - // half of the thumb width value from jspsych.css, used to adjust the label positions - var half_thumb_width = 7.5; - var html = '
'; - html += '
' + trial.stimulus + "
"; - html += - '
'; - // Draw horizontal line in VAS container - html += - '
'; - // Draw vertical line, but hide it at first - html += - ''; - html += "
"; - html += "
"; - for (var j = 0; j < trial.labels.length; j++) { - var label_width_perc = 100 / (trial.labels.length - 1); - var percent_of_range = j * (100 / (trial.labels.length - 1)); - var percent_dist_from_center = ((percent_of_range - 50) / 50) * 100; - var offset = (percent_dist_from_center * half_thumb_width) / 100; - html += - '
'; - html += '' + trial.labels[j] + ""; - html += "
"; - } - html += "
"; - html += "
"; - html += "
"; - - if (trial.prompt !== null) { - html += trial.prompt; - } - - // Submit button - html += - '"; - - display_element.innerHTML = html; - - var vas = document.getElementById("jspsych-html-vas-response-vas"); - // Add minor ticks - for (var j = 0; j < trial.labels.length; j++) { - var label_width_pct = 100 / (trial.labels.length - 1); - var pct_of_range = j * (100 / (trial.labels.length - 1)); - var mtick = document.createElement("div"); - mtick.style.position = "absolute"; - mtick.style.height = trial.scale_height / 2 + "px"; - mtick.style.width = "2px"; - mtick.style.top = trial.scale_height / 4 + "px"; - mtick.style.background = trial.tick_colour; - mtick.style.left = (pct_of_range / 100) * vas.clientWidth - 1 + "px"; - vas.appendChild(mtick); - } - - // Function to move vertical tick - var pct_tick = null; - var vas_enabled = true; - var clicks = []; - vas.onclick = function (e) { - var clickTime = performance.now() - startTime; - if (!vas_enabled) { - return; - } - var vas = document.getElementById("jspsych-html-vas-response-vas"); - var vas_rect = vas.getBoundingClientRect(); - if (e.clientX <= vas_rect.right && e.clientX >= vas_rect.left) { - // Compute click location as a proportion of VAS line - pct_tick = (e.clientX - vas_rect.left) / vas_rect.width; - // Round to nearest increment, if needed - if (trial.n_scale_points) { - pct_tick = Math.round(pct_tick * (trial.n_scale_points - 1)) / (trial.n_scale_points - 1); - } - var vline = document.getElementById("jspsych-html-vas-response-vline"); - vline.style.left = pct_tick*vas_rect.width - 1 + "px"; - vline.style.visibility = "visible"; - // vas.appendChild(vline); - var continue_button = document.getElementById("jspsych-html-vas-response-next"); - continue_button.disabled = false; - // record time series of clicks - clicks.push({ time: clickTime, location: pct_tick }); - // call - if (trial.resp_fcn) { - trial.resp_fcn(pct_tick); - } - } - }; - - var response = { - rt: null, - response: null, - }; - - function end_trial() { - jsPsych.pluginAPI.clearAllTimeouts(); - - // save data - var trialdata = { - rt: response.rt, - stimulus: trial.stimulus, - response: response.response, - clicks: clicks, - }; - - display_element.innerHTML = ""; - - // next trial - jsPsych.finishTrial(trialdata); - } - - var continue_button = document.getElementById("jspsych-html-vas-response-next"); - continue_button.onclick = function () { - // measure response time - var endTime = performance.now(); - response.rt = Math.round(endTime - startTime); - response.response = pct_tick; - if (trial.response_ends_trial) { - end_trial(); - } else { - vas_enabled = false; - } - }; - - // hide stimulus if stimulus_duration is set - if (trial.stimulus_duration !== null) { - jspsych.pluginAPI.setTimeout(function () { - var stim = document.getElementById("jspsych-html-vas-response-stimulus"); - stim.style.visibility = "hidden"; - }, trial.stimulus_duration); - } - - // end trial if trial_duration is set - if (trial.trial_duration !== null) { - jspsych.pluginAPI.setTimeout(end_trial, trial.trial_duration); - } - - var startTime = performance.now(); - } - } - jsPsychHtmlVasResponsePlugin.info = info; - - return jsPsychHtmlVasResponsePlugin; -})(jsPsychModule); diff --git a/packages/plugin-html-vas-response/examples/index.html b/packages/plugin-html-vas-response/examples/index.html index e5ecd8db..4f780d87 100644 --- a/packages/plugin-html-vas-response/examples/index.html +++ b/packages/plugin-html-vas-response/examples/index.html @@ -2,10 +2,9 @@ - - - - + + + diff --git a/packages/plugin-html-vas-response/index.js b/packages/plugin-html-vas-response/index.js index e02beae7..672c57b1 100644 --- a/packages/plugin-html-vas-response/index.js +++ b/packages/plugin-html-vas-response/index.js @@ -3,95 +3,149 @@ var jsPsychHtmlVasResponse = (function (jspsych) { const info = { name: "html-vas-response", + version: "2.0.0", parameters: { + /** The string to be displayed. */ stimulus: { type: jspsych.ParameterType.HTML_STRING, pretty_name: "Stimulus", default: undefined, }, + /** Specifies the labels to be displayed, equally spaced along the scale, as in jspsych-html-slider-response. */ labels: { type: jspsych.ParameterType.HTML_STRING, pretty_name: "Labels", default: [], array: true, }, + /** A function called when the participant clicks on the scale. + * The current location of the participant's response (between 0 and 1) is provided as an input. */ resp_fcn: { type: jspsych.ParameterType.FUNCTION, pretty_name: "Response function", default: null, }, + /** Specifies whether smaller vertical tick marks should accompany the labels. */ ticks: { type: jspsych.ParameterType.BOOL, pretty_name: "Ticks", default: true, }, + /** If the scale should have some set of discrete clickable points (such that the tick mark will be rounded to the nearest such point), + * this parameter can be used specify the number of such points. If not, set this to `0`. */ n_scale_points: { - type: jspsych.ParameterType.BOOL, + type: jspsych.ParameterType.INT, pretty_name: "Number of scale points", default: null, }, + /** The width of the VAS in pixels. + * If left `null`, then the width will be equal to the widest element in the display. */ scale_width: { type: jspsych.ParameterType.INT, pretty_name: "VAS width", default: null, }, + /** The height of the clickable region around the VAS in pixels. */ scale_height: { type: jspsych.ParameterType.INT, pretty_name: "VAS height", default: 40, }, + /** The colour of the scale (the horizontal line). Anything that would make a valid CSS `background` property can be used here. */ scale_colour: { type: jspsych.ParameterType.STRING, pretty_name: "Scale colour", default: "black", }, + /** The style of the cursor when the clickable part of the scale is hovered over. */ scale_cursor: { type: jspsych.ParameterType.STRING, pretty_name: "Scale cursor", default: "pointer", }, + /** The colour of the participant's response marker. Anything that would make a valid CSS `background` property can be used here. */ marker_colour: { type: jspsych.ParameterType.STRING, pretty_name: "Marker colour", default: "rgba(0, 0, 0, 0.5)", }, + /** The colour of the tick marks on the scale. Anything that would make a valid CSS `background` property can be used here. */ tick_colour: { type: jspsych.ParameterType.STRING, pretty_name: "tick colour", default: "black", }, + /** The content to be displayed below the stimulus. */ prompt: { type: jspsych.ParameterType.HTML_STRING, pretty_name: "Prompt", default: null, }, + /** The text of the button that will submit the response. */ button_label: { type: jspsych.ParameterType.HTML_STRING, - pretty_name: "Buton label", + pretty_name: "Button label", default: "Continue", }, + /** If `true`, the participant must select a response on the VAS before the trial can advance. */ required: { type: jspsych.ParameterType.BOOL, pretty_name: "Response required", default: false, }, + /** The duration, in milliseconds, for which the stimulus is visible. + * If `null`, the stimulus is visible for the duration of the trial. */ stimulus_duration: { type: jspsych.ParameterType.INT, pretty_name: "Stimulus duration", default: null, }, + /** + * The duration of the trial, in milliseconds. + * Once this time elapses, the trial ends and any response is recorded. + * If `null`, the trial continues indefinitely. + */ trial_duration: { type: jspsych.ParameterType.INT, pretty_name: "Trial duration", default: null, }, + /** + * If `false`, the participant's clicking the continue button does not end the trial (but does prevent any changes to the VAS response), + * and the trial ends when `trial_duration` has elapsed. + */ response_ends_trial: { type: jspsych.ParameterType.BOOL, pretty_name: "Response ends trial", default: true, }, }, + data: { + /** The response time in milliseconds for the participant to make a response. + * The time is measured from when the stimulus first appears on the screen until the participant's response. */ + rt: { + type: jspsych.ParameterType.INT, + }, + /** The value selected, between 0 and 1. 0 is the leftmost point on the scale, + * 1 is the rightmost point, and 0.5 is exactly in the middle. */ + response: { + type: jspsych.ParameterType.FLOAT, + }, + /** The stimulus displayed during the trial. */ + stimulus: { + type: jspsych.ParameterType.STRING, + }, + /** + * A record of the participant's clicks on the scale. Each element in the array is an object with properties `time` + * (the time of the click, in milliseconds since the trial began) and `location` + * (the location of the click on the VAS, from 0 to 1). + */ + clicks: { + type: jspsych.ParameterType.COMPLEX, + }, + }, }; + class jsPsychHtmlVasResponsePlugin { constructor(jsPsych) { this.jsPsych = jsPsych; @@ -203,10 +257,11 @@ var jsPsychHtmlVasResponse = (function (jspsych) { pct_tick = (e.clientX - vas_rect.left) / vas_rect.width; // Round to nearest increment, if needed if (trial.n_scale_points) { - pct_tick = Math.round(pct_tick * (trial.n_scale_points - 1)) / (trial.n_scale_points - 1); + pct_tick = + Math.round(pct_tick * (trial.n_scale_points - 1)) / (trial.n_scale_points - 1); } var vline = document.getElementById("jspsych-html-vas-response-vline"); - vline.style.left = pct_tick*vas_rect.width - 1 + "px"; + vline.style.left = pct_tick * vas_rect.width - 1 + "px"; vline.style.visibility = "visible"; // vas.appendChild(vline); var continue_button = document.getElementById("jspsych-html-vas-response-next"); diff --git a/packages/plugin-html-vas-response/package.json b/packages/plugin-html-vas-response/package.json index d22333da..21783540 100644 --- a/packages/plugin-html-vas-response/package.json +++ b/packages/plugin-html-vas-response/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-html-vas-response", "devDependencies": { - "@jspsych/config": "^2.0.0", - "jspsych": "^7.0.0" + "@jspsych/config": "^3.0.0", + "jspsych": "^8.0.0" } } From f7ef97189e499d6827b968f0267130cce7ecd966 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Mon, 14 Oct 2024 06:10:28 -0400 Subject: [PATCH 14/30] update plugin-html-swipe-response to v8 --- package-lock.json | 656 +++++++++++++++++- .../examples/example.html | 16 +- .../plugin-html-swipe-response/package.json | 6 +- .../src/index.spec.ts | 5 +- .../plugin-html-swipe-response/src/index.ts | 85 ++- 5 files changed, 724 insertions(+), 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index e42a557e..e815c469 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20736,12 +20736,662 @@ "interactjs": "^1.10.17" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" }, "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-html-swipe-response/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-html-swipe-response/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-html-swipe-response/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-html-swipe-response/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-html-swipe-response/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-html-swipe-response/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-html-swipe-response/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-html-swipe-response/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-html-swipe-response/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-html-swipe-response/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-html-vas-response": { diff --git a/packages/plugin-html-swipe-response/examples/example.html b/packages/plugin-html-swipe-response/examples/example.html index c43ec0f1..cff6e252 100644 --- a/packages/plugin-html-swipe-response/examples/example.html +++ b/packages/plugin-html-swipe-response/examples/example.html @@ -1,20 +1,20 @@ - + - - - + + + + - + + - + - + + - + - + + - + - + + - + + - - - + + + + - - - + + + - - + + + + - + diff --git a/packages/plugin-libet-intentional-binding/index.js b/packages/plugin-libet-intentional-binding/index.js index 837b796d..913a6ff9 100644 --- a/packages/plugin-libet-intentional-binding/index.js +++ b/packages/plugin-libet-intentional-binding/index.js @@ -3,6 +3,7 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { const info = { name: "libet-intentional-binding", + version: "2.0.0", parameters: { cond: { type: jspsych.ParameterType.STRING, @@ -45,13 +46,13 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { }, instructions: { type: jspsych.ParameterType.HTML_STRING, - pretty_name: "", + pretty_name: "Instructions", default: "", description: "The instructions shown to the participant during estimation.", }, instructions_wo_keypress: { type: jspsych.ParameterType.HTML_STRING, - pretty_name: "", + pretty_name: "Instructions without a keypress", default: "", description: 'The instructions shown to the participant during estimation if they did not make a keypress. E.g., "When did you feel the urge to make a keypress?". Only applicable if hand_est and est_wo_keypress are set to true. If left undefined, the parameter takes on the same value as instructions.', @@ -182,19 +183,19 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { }, num_start: { type: jspsych.ParameterType.INT, - pretty_name: "", + pretty_name: "Starting number", default: Math.PI / 2, description: "Where to draw the first number, in radians.", }, num_font: { type: jspsych.ParameterType.STRING, - pretty_name: "", + pretty_name: "Font size", default: "5mm Arial", description: "The font for the numbers.", }, num_dist: { type: jspsych.ParameterType.INT, - pretty_name: "", + pretty_name: "Number distances", default: 30, description: "Distance of the numbers from the outer circle of the clock, in pixels.", }, @@ -205,6 +206,54 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { description: "Length of the clock hand in pixels", }, }, + data: { + /** The condition of the trial ("baseline-key", "baseline-tone", "operant-key", or "operant-tone"). */ + cond: { + type: jspsych.ParameterType.STRING, + }, + /** Specifies whether the participant pressed a key too early. */ + early: { + type: jspsych.ParameterType.BOOL, + }, + /** Specifies whether the trial timed out due to the participant's lack of response. */ + timeout: { + type: jspsych.ParameterType.BOOL, + }, + /** Object that describes the various important quantities (all in radians, clockwise is positive) */ + theta: { + type: jspsych.ParameterType.COMPLEX, + parameters: { + /** Where the clock hand begins spinning. */ + spin_start: { + type: jspsych.ParameterType.FLOAT, + }, + /** Where the clock hand was when the participant pressed a key. */ + keypress: { + type: jspsych.ParameterType.FLOAT, + }, + /** Where the clock hand was when the tone was played. */ + tone: { + type: jspsych.ParameterType.FLOAT, + }, + /** Where the clock hand was at the beginning of the animation. */ + estimation_start: { + type: jspsych.ParameterType.FLOAT, + }, + /** Given the current condition, this is the degree that the participant must estimate. */ + target: { + type: jspsych.ParameterType.FLOAT, + }, + /** The estimation provided by the participant. */ + estimate: { + type: jspsych.ParameterType.FLOAT, + }, + /** The amount in which the participant overshot the target angle. */ + overshoot: { + type: jspsych.ParameterType.FLOAT, + }, + }, + }, + }, }; /** @@ -278,17 +327,17 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { prompt_div.style.visibility = "hidden"; display_element.appendChild(prompt_div); - //Create a canvas element and append it to the DOM + // Create a canvas element and append it to the DOM var canvas = document.createElement("canvas"); display_element.appendChild(canvas); - //The document body IS 'display_element' (i.e. .... ) + // The document body IS 'display_element' (i.e. .... ) var body = document.getElementsByClassName("jspsych-display-element")[0]; //Get the context of the canvas so that it can be painted on. var ctx = canvas.getContext("2d"); - //Declare variables for width and height, and also set the canvas width and height to the window width and height + // Declare variables for width and height, and also set the canvas width and height to the window width and height canvas.width = trial.clock_diam * 2; canvas.height = trial.clock_diam * 2; var middle_x = canvas.width / 2; @@ -458,20 +507,12 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { // load audio // If you did not specify the tone file, the tone loading will be skipped. if (trial.tone_file != null) { - var context = jsPsych.pluginAPI.audioContext(); var audio; - // load audio file + this.jsPsych.pluginAPI - .getAudioBuffer(trial.tone_file) - .then((buffer) => { - if (context !== null) { - audio = context.createBufferSource(); - audio.buffer = buffer; - audio.connect(context.destination); - } else { - audio = buffer; - audio.currentTime = 0; - } + .getAudioPlayer(trial.tone_file) + .then((player) => { + audio = player; ctrl_fcn("start trial"); }) .catch((err) => { @@ -556,13 +597,8 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { // schedule tone setTimeout(function () { // play the tone - if (context !== null) { - var startTime = context.currentTime; - audio.start(startTime); - } else { - audio.play(); - } - // record cock hand angle of audio + audio.play(); + // record clock hand angle of audio trial_data.theta.tone = clock.theta; trial_data.tone_ms = performance.now(); // trigger estimation? @@ -654,15 +690,9 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { // function to end trial when it is time function end_trial() { - // kill any remaining setTimeout handlers - jsPsych.pluginAPI.clearAllTimeouts(); - // kill keyboard listeners jsPsych.pluginAPI.cancelAllKeyboardResponses(); - // clear the display - display_element.innerHTML = ""; - // compute error var est = trial_data.theta.estimate; if (est < 0) { diff --git a/packages/plugin-libet-intentional-binding/package.json b/packages/plugin-libet-intentional-binding/package.json index d75601fa..f4d72e34 100644 --- a/packages/plugin-libet-intentional-binding/package.json +++ b/packages/plugin-libet-intentional-binding/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-libet-intentional-binding", "devDependencies": { - "@jspsych/config": "^2.0.0", - "jspsych": "^7.0.0" + "@jspsych/config": "^3.0.0", + "jspsych": "^8.0.0" } } From c95db7dd486193d6a8f0abb32a8e44ea3a1c68ab Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Wed, 16 Oct 2024 04:58:55 -0400 Subject: [PATCH 22/30] update plugin-vsl-animate-occlusion to v8 --- package-lock.json | 656 +++++++++++++++++- .../docs/jspsych-vsl-animate-occlusion.md | 7 + .../examples/example1.html | 7 +- .../plugin-vsl-animate-occlusion/package.json | 6 +- .../plugin-vsl-animate-occlusion/readme.md | 1 + .../plugin-vsl-animate-occlusion/src/index.ts | 18 +- 6 files changed, 684 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8afc5d01..c3842c94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28112,13 +28112,663 @@ "snapsvg": "^0.5.1" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", "@types/snapsvg": "^0.5.1", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" }, "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-vsl-animate-occlusion/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-vsl-animate-occlusion/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-vsl-animate-occlusion/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-vsl-grid-scene": { diff --git a/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md b/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md index 3851f274..469a2410 100644 --- a/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md +++ b/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md @@ -4,6 +4,13 @@ The VSL (visual statistical learning) animate occlusion plugin displays an anima Fiser, J., & Aslin, R. N. (2002). Statistical learning of higher-order temporal structure from visual shape sequences. *Journal of Experimental Psychology: Learning, Memory, and Cognition, 28*(3), 458. +## Dependencies + +This plugin has a dependency on [Snap.svg](http://snapsvg.io/). In order to run it, you must include the corresponding script in the header as such: +```javascript + +``` + ## Parameters In addition to the [parameters available in all plugins](https://www.jspsych.org//overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Other parameters can be left unspecified if the default value is acceptable. diff --git a/packages/plugin-vsl-animate-occlusion/examples/example1.html b/packages/plugin-vsl-animate-occlusion/examples/example1.html index eb8cd776..fd7572e9 100644 --- a/packages/plugin-vsl-animate-occlusion/examples/example1.html +++ b/packages/plugin-vsl-animate-occlusion/examples/example1.html @@ -1,10 +1,11 @@ - - + + + - + ``` diff --git a/packages/plugin-vsl-animate-occlusion/src/index.ts b/packages/plugin-vsl-animate-occlusion/src/index.ts index f68becac..f1ade8e9 100644 --- a/packages/plugin-vsl-animate-occlusion/src/index.ts +++ b/packages/plugin-vsl-animate-occlusion/src/index.ts @@ -3,6 +3,7 @@ import Snap from "snapsvg"; const info = { name: "vsl-animate-occlusion", + version: "2.0.0", parameters: { /** Array containing path(s) to image file(s). */ stimuli: { @@ -57,6 +58,21 @@ const info = { default: 500, }, }, + data: { + /** Array containing all response information. Each element in the array is an object representing + * each valid response. Each response item has three properties: `key` the key that was pressed, + * `stimulus` the index of the stimulus that was displayed when the response was made, and `rt` + * the response time measured since the start of the sequence. This will be encoded as a JSON string + * when data is saved using the `.json()` or `.csv()` functions. */ + response: { + type: ParameterType.COMPLEX, + }, + /** Array where each element is a stimulus from the sequence, in the order that they were shown. + * This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. */ + stimulus: { + type: ParameterType.COMPLEX, + }, + }, }; type Info = typeof info; @@ -204,8 +220,6 @@ class VslAnimateOcclusionPlugin implements JsPsychPlugin { } const endTrial = () => { - display_element.innerHTML = ""; - this.jsPsych.pluginAPI.cancelKeyboardResponse(key_listener); var trial_data = { From bb380497a6ff7f0ee1abb1454bc3ddb292cc355c Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Wed, 16 Oct 2024 05:28:04 -0400 Subject: [PATCH 23/30] add example and update plugin-video-several-keyboard-responses to v8 --- package-lock.json | 656 +++++++++++++++++- .../examples/example.html | 40 ++ .../examples/fish-spin.mp4 | Bin 0 -> 169080 bytes .../package.json | 6 +- .../src/index.ts | 29 +- 5 files changed, 719 insertions(+), 12 deletions(-) create mode 100644 packages/plugin-video-several-keyboard-responses/examples/example.html create mode 100644 packages/plugin-video-several-keyboard-responses/examples/fish-spin.mp4 diff --git a/package-lock.json b/package-lock.json index c3842c94..7545315b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28096,12 +28096,662 @@ "version": "2.0.0", "license": "MIT", "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.1.2", - "jspsych": "^7.1.0" + "jspsych": "^8.0.0" }, "peerDependencies": { - "jspsych": ">=7.1.0" + "jspsych": ">=8.0.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-video-several-keyboard-responses/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-video-several-keyboard-responses/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-video-several-keyboard-responses/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-vsl-animate-occlusion": { diff --git a/packages/plugin-video-several-keyboard-responses/examples/example.html b/packages/plugin-video-several-keyboard-responses/examples/example.html new file mode 100644 index 00000000..7335ea78 --- /dev/null +++ b/packages/plugin-video-several-keyboard-responses/examples/example.html @@ -0,0 +1,40 @@ + + + + + + + + + + + diff --git a/packages/plugin-video-several-keyboard-responses/examples/fish-spin.mp4 b/packages/plugin-video-several-keyboard-responses/examples/fish-spin.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..6802564a6be090dce6ba461dde7d1d526b16a12b GIT binary patch literal 169080 zcmV)YK&-z2001Cnba`-Tb8l?`00IDMb8l^Fb8j+Xc4IMZa5OOh000PPa%E)z0*iWW zWMOmw003DA1uoo0>AmLJNVk?O*dW;>?(cXqHZ&kDAY*TGWgsy%H6U^_IWRFGH)Jqo zW->AW1tp~1^*<8|DIA;D8o&bPxuG#NF*!FjGBG$dI59CZGchSoY@&3o4 zt<=96vH$=B0AT_kBaeLiy2Fva^WEq9c-p;c+(GewBx+_D?+Q)(boD0q$)L7vO$t;h6IriVj}VfA-5v;wco}Bm9^w)}ppwL%1JovL=-%Fa6w6L*{v_A!Mo4DSqc}v54(8t^xOJwFzst z6H#IUNxPo3g^G>0|LZxQ&r&Rp?&Bii&cy%l;`UM`DKw`Ne#TVU!WigJBKQkMBY^`` za$NXF?KIJ{@#IU$*SYvzt4^!kGz<-~3Ucrsnuj@>YoWyk2+D3b;1)$*T+%2G?xx-f zo+Qhe5Qz~G4c)~~Mur?{%ZeRC&k!?~h@fI-?vMX~1Xd}=f_^?kS4YoK0AbVaXXeD< z=||EP++Uz0*auA>N9zQgrBHEqGw8P*r4y`qz+qJCgcudDDRDqbB2h7K61gMK^G8@z zV3`*!1X%0is;fXJ#=(ru(|51~G6*hyE}*!*8alhQXe3+Ekzs41Uk2 z5k^+ID>^AJcoN^k8bP1Qz8Ad>;!&FXy<_=09~y{eG$8(vW@<;LUSDbMWQpo-3jW+_ zY+@mO^7qKg^x|=tvJ6~5yna;D3y%c&1`{ve6~rt%%Y|8Q(`tDpZjg2O^dsPo<#t|( z*Z+oCE{dbXW!x7pZ|!nV-rH`ci~#(vXA=sSD_=bGKmTMtBA?<&4r_yG z_`THU?aQK}_hLv2D~F5$ivV~?Te97wqvo%JWs3nd(k|SLM4OHuLuKS^hlv{_h;8SE zmtAgKKu7Y4>tu|5oLK*mbMV~useJ&B4rX?r1QnK=lC|45>uPq02@?V^Jd@Hv`BCP zCJJpPSq=s1B7RyZO{}NeM$%bWyZPAwfJ?e>u&Hqwb1U*hMOY+op|dWb#}+Y~XtNf; zKomq}I`_(aqq!W&qS4;oDVidQOFe4UDD5`rh5~L ze^~nGVAIKu{OJ-*KL88vdFTLMh$@mCXeuqg*+ zSSkxNYDyL^p7f}EvP+gM$;GGS`uBD8&;;$afk~}mf72D4H@*-4o3sP*KL`Jz_LGOi zE5MiYA=J2;LsnJNj-LJ>Y#*L5O-roZGQvLwGTLPd#FZ+}G^Aa!+l6%Zc3UWvrkwRz zlts9$Tu)KV5HT-Y)`s@e+xdi?{^r!T0OB4WDCvWYg)r7$AHTkQXYC_D8!<%t$lW8q zuH-oDjdbEudbRGxN)8!Pj4}o3Nvd#JqYcHXV=+J|WG*tQYKOq|u>%a}xngtK?68(l z3Pmumt4K7DPgf9pqICP`9AJ`-Kq$!K@)2!H@1<2XkG>o;D{^k_aZe&aXXLb0c1@UDf5^tH>v0XRd*4OHa|FJDigLB0l}m zU@tinpJOWj7!j}rL0kHgQ7Mpwo%L*|*G`UL(qhnG$H{54{RX&$zoPjsG-A3ezMy|| z6p1iNXt?D;I|=nXxWej!=qUiS3KF&Vmq|=ceDD~vE$$G;Wvf;uC`B7+ zzo9&q`PTTs7QL?<=FB~)|KbYI_1b~#sE6iN0U(gLQrJ~=VgrFc;cSX%G~0A)awH@& z=|4xZCKDj|{nMU2MQ0W_v&~wgXA-fCQi41oFo4c-emVjdf(kL~_I zb;p3Lp=>+5%ZFhAZ}xlEk%`r{kQdT2pFmkga||hHg^4MmMqi#|c~O+u6c;*l8EBtO zfR`HTQ$?l37l6|^0|0~wM39$ja^4cbfM{Ee14YpRn!$E6p{|}p7PLnS=TP|W?`r*+ zN>rnQA}>zEx$fZwQlt4l|8j|wR9cXDmb=^FdA|WIM2YuSm|0)9M$v$db&)M4)tA%<)R-*+I+&o4fGhHZbiBmis4<(<7=wGROCWbse;!* zoT0&DBIN``_s$xE3TQzaewV&maN7T`7fgs|e{R&waQ;}!;~!)-<)nIAMEMSrW`h`G zp6CZOMD_i$I|9ojLm)5zrXr1ta<*tjsnW>*ESVC6e2K)^55&K41KoCK(E>`?y}5El z%EY@m@TzkUl&Yf&;yK-NtUt6X>wK&W;UyObrNxkjfmH2!32%WrME?mZr=<0xQL^n6 z_Gl<2BKztpxfEOhe$$~4eWp6uFgIwuKuMY#iBVaODCpx5a&S-{xe+l?N^5V}?f9lGFb#^P#*)FH#1d;PBd~|(Xp3eA0WqGmNq?YdU;!O>3<_S^uj5Q%;n$VtPLU} zp9ze5i%H@b8dUTzf2#&*&Ut?Ns!0Xe=zVFeih)owwUHKK+BX-HIfUU*e%y%hm;1R4jy~ zha$9E#@m`@%n=L0j!#mpEV%kDsXki5TkPD!ecP(^Yb{Pe469N(YFG=D9o!x5;^x?A z)140Jje?GU&e>Gc9eDkwq1=pUGOk(i6s>-@*7}*miuG4}4tbb9eFx2 zWq3y19(4OZSvnRo3;g7j-?qUa1D^x;F1#=`K%Fl%*#CDGv3z}A5j40+J+N2*=~?v( z2irKG1V->l$#;D{6nu-L_6QmRAiE|R?q!@wpQyEEFab)Q4;}!Ha7|kt;Eb1ZV$izt zJj$NNuhFNYX(Zi{&Iy?ce&H4F)iv%muB=E|lDas*&*N2R>b=)}k2AGd^JN$-cW)hq zFex9$Vta<%2Z%V4!ID2psu_Gr<7s+foBz2`;2=n*5KTnKkXBF;6slCawoGshzyJg_ z{pMOQHz{A;MD0hwSLlo4Q33@Rmq$GcMc-d819^LoN0Cy!_6t4rgx83sgICMSyg-Of zzQ_D7#(z5u65*Z;WtV)Oe%Tvoq_MfQNwrS$8MaP*P$0>9+!8!u1USK3A@N>05OmkI zyZrVr5oJ0VjB0P$a;+qC1xgo(5Xl!KJ2iWE3FR1Tlg;_P&GyL)WlGT=AJqWaH+W@zbRwRY|CG!N5$ z&rck(!0C>;k3w^F;ImNsbj8;|gQ+%;5QaRhPl5MpeY=5PE4@^~A=zEZxVeE&jWX`X zXeqUS+qtD1gv-pa4b?{GU84J6CXySQ0`|l6MjdYvdU^q3F8DkIF8f0jnkOA!AC{WIm8q%y@G#^<4Qh%CB0uMGboET7x z-#wx}+hguhr=`8gFItgNeU&Zso>CLxam&9Z;bv@Zzl%<|I{gSWqiZG^Dc_r1hE4_B z;C@y4Md8X(JSzI!mkq!{irDn+Xy@nr@Bw zwrtkUY;)D`1&j!ck7J_j(MdXZ|@nx;Rl6SP6p>NAXO zDje1Zk7fWLt1O~~gP_N>ll0*k*i|F|I%BJq>*o~$n>Q>f>UOiyMeD`t4^XzKA})_G zls~XXTY&F{{(=`c!x~y3jQ}cLN2Xr_x_N^+wlV0kV8dP#-MpGXdY6l7I+3xMi)bnB zf`XuR-w>8Q`hmNy8O$^QI^*koN~%rt@DuzPKcgEkyVK?|%ke_mWFh$4`8s7=4YIS? zF!+jkVWBteSGpQ@B`b+I*;IRLf6>M^YLLtB&`0)DhfqMxv$Cw56qLTG*;3_?!}DCA zS%kO$e90SM3&TY)H0Hg+$Q{u?^H7WYKX}b>rfIx9p&BlUy;m{>6k)W9fm?_nm;o3S z5q-ylW4suas{Jof^d8@up9Y^i>3$rYt5d}#7zYKfvz=x@z07|J3fySrFKj?@>_5xa z)6<8i@H*u=em0BsB0=D_H0Sfp@+lrIR#^ryh-Y%k;FEK-C+z-+2Q2ru_k^~r1VrmP zu;+-;3lYkk(Nw#Q4@LLJGcV)50000)0iHtgKmP+iphSy*$YUn}P)9(1jz&!ZM|Bl= z@1;02bznY~M9w0UehDMrpaze=Tpg%yk|1B&v{~xWtJ5{x-FPJ7000HLL7GZ+!IU`d5Ua;E;skW}gIIzZBX*34dQG1}#8(Vk_F7}+DiYx@R=8-cl?CYKDY0=V?vuhbVZlhTCVzvD*bzBc*6bYe(Av8zVudGzs{PaCbr67ixdJV+OekKsB}Gh> zEv24udf4N}Qb#jY85(G8dcOA79i4T2%xJ;jGlAmezHI&?OSjvF+JvLUsaPre3r9Gp zIj_(UvulF4uP3y*BDpKrvJ-cuqNbr|k%-J_qM&ghN7}d@!(NQP+;oOI1Pd<%u!$D#9$Z2`%-&nv@HALj zA|)TeTBt=Y9Nek{x$%ibM5ub5;HxSNiJa;k072D@|4m)~_y9g+I{YFl*VbD*B%M@u zMXLA@<3q&~kOVe6l-rYFSXLLiOE+1fy&YVE9YG{9%F;(Ui`jmcjAOqcbrKq%U(+}q zN-QINyNtDXb*WT-d$%W`YoLz|(X#k%PHf9BJ0&d7Va)6-v4!fCgnIX=eT}kn%Ml%(4}g91)a5P0}Lsk-q1QS^8jSSzx(p z@q*7^G(y=v*`!K$S1!u-ID;SwSJ#XL+oSU0U{}1j`Xpg&s?%G@4<9|p)&vBvB{tW9fPmwu`k~xo$&S z^J2{UYk&v<57-h9Ay7t{Ev%&|&U98fdKz3hGVh?KlffUOu^w;D=U_V#jgV=AuARtN zS3Li}Qau9V8jd;zrkapij`-^w?@1af91AFIWu3OO!0glzenEaS0k8KHofZLWce{fF zr4-$5C+gD4rwj%=_sb&7khAo4Xm;>4g`O+w*-rsBw2YmsQGxb>IF|?J^l>bzW`(G- z%z5^@Y?qsYEhv)tN$;TlwRpJsa2n;VB!#ME797*ZNsmub+7(gHk1DDPPbl? zv7T@M01MbdG2!XHjX-WHr5nlYPYnj@dTIN>`B>Q|71UT-n$sLQyboFa#@&J??P?2Z z7~^n4#v4~D;1(7!{*V);f_tsn@C3v<3w5#LI{$tOfz=q*{9NoPt>I6c3sFe=3uhR;zC-5^yR-AQ1HWkOW> zTk?XBzU`Cb+_fD2DFmc+zYjLX<05<2p6qNw7oh>qjr7HHhRHs%kS;#BE z;0B|IBFEIK9`BXf^tgp8wK8Qp_Yx3KT6mjwPOiQ>^jC>0??=Y&xCsvK@*7Pye(hj# zCRXSGLn1dyq8P8b4@tiW{3DdU7{PZ4fP|wJPncI@T&{SwtrK{?<(ol>RRz@*%5)K6cgb znig_}7>5Zn*ml0V_cn$5VkN0SJLt6s+or#b>ie+^qZp8BbN`3t87l4PYDkhZ%Kxx= zBtVj}7Lv>=B}`Ws*#e3tla|fj9u8LPk<$IE)#pAT5a-UDPL!w-uuXv#$y z?a+>f%_r*m2U;^vCj96tLy{-=k>ZfxY(?eV05TwfMf|GXpN)B5Fu!_UtO#)lIXY3YEi$T%$vmI06i#d&4Ri56pOanmZIUcI zPC3)xdf1ImQu8&%8RuSubN6YQvl%{0deeV1JWf&GpSthR<`ZRjP!c(y@ZoR@Tm646 zkjU&j>QERIiZ56qoVu2Gp5s|pweQ6f?C=l>;|VLOe|Fsq(k`~rPy#nb!A5K-tCsu- zt@A2*=UNkdC^WNdJn1Xrtgb^u5?&QRS@4-v%z`(#k9^W7Z^ZXj5?*`ig8QW^N9Kwy zGBV6^vp;Ky3(99}{vIOqe(YNLs8lvH5#NqWY+2mz8;45}FqXTNbOh*~Okz%<9~GTa zlw;Jt*`HQ_B_w?H^y5=Jyol_LPRyA+K2L!F002h;o@msM|2~*|N`g*the$3m83sNK z>k?=YHE2Kf9@=3y{?_sBO4h6&d@T_>XI~+NLKQH%9)ewx!&s?#kGZYJ{tI(MrA+_; z1QkJ=Y?JFm!k9<@^OCl8j+_R=fQV!PSc>Z(tcb{bp4{weCv^lt!*U7wFgQ_JOpMS_ z7oNc+8thQ(_E9*_%ceBqAsB*zMR%TN6g)~c#{4y3x1Oet>Fzji-woAW`n4|R6E!x3 zuEdj5jc2C-t9#oM93u za~~+;b@`NY^}C#?*dmb@80>;k-@@PUtFrk!YvOJMg%`ZlaF?es2J@VODfsrxD;U=t z<4yYj?3x!J6>wqcY*IGCMZUXY-a^GIQ(R*WTn-k*`D700+kI0n;%8m}i1dY8qRMfF z{)QNL>Xe3s*~V~a!;N80snEr0t-FxxEvkoG06kwBM;BkB!~H#f9c8QOD*&7XAN@G6 z*(LOI8j{s@Q!tz9%|@ciET6zQ(SJmMjGs~N|KE(8K(v;OpnsLG5U&bErN~_ zBDFShBaCMHy=RxXt;S#jAskS_1p0Dof?d(No9CvvRq;TU;OA8N=YFl^oEu-2LyVpo zZNkXT5>T5@&#>(}+sHj_d?~$=-vG*CL2I&MX=W|LIqu2^Q*X0tp?*nPN#< z@zMQu5h1C`^xD2%moj%l!>1P79cA*`J(Q$d*Hxp7I2Q4)^UF(i?b!2e647-6N13uK zr>4iNNeCQ#kdh{3ip7ei0A{!>jDkDqDEnklAm8l3)^!7hRf=VQ9Gj2B1+v&^vUX?f zNrQgh+}FVFTGMPnnm6v&4g7@iA()j9%O%H&Xci4=*s2zcW{03T=rso7AtkWMK6ZpS zf;>|nr_Ojp7!=yazGx2cxSe8Q0~cvmB$hk+w7HUTo+*sSwcVAg7#`3CYiAG;4mJTA z#*mWqOpN?xJ}QwFUqB+bP15MIA^VN6N>`oImXgWAH~8SMpRpdsQ#4;zH@YrYp%-gv zf&}&I|5oUUkn`o(pYP3Txf>!-JXE*3{O;^SUQ!fcpjjhX0yGZ4U>?GrK{t+kd*1kp z6yiBndS3$o00W~znvRqDM8Kv;|MM+g25>Y0aK;A{IXqASx~w*ufRU77*}acx=tE)k z7>F`_%Z7D$5IN7q0)N1h>2Z?|4~T`0%;|3db>c5a3#oSXi~sb$9)SL0R36Pa%1Tet z4&EXFHh>Sfz!VQxHM2_+XO}1?dmi*0XkX*!-zH#AutD2~dKm2vr}3-q+W(06*u!J% zY%vYb|HLYtdtyZ}@ZyEBWI?v=Y@~z7#9v$$-gTIX9=;2FeY+~N!^MRu@VtMjpN}OqCxnI)^*eGj}tX5gdCJfoy{XtY6KCu5aYg(!l z=P#Q(cjBhM^fv^g!I#Sc5k%sgzKu7jhPcRAl@gfw)g;9$ z~)^M5KrT zx7AY!2>af!5HIlvLrZapPIL}UzI8Z}C4@jKXsXPk3-$0RtUB}T=+%A?$2jv59}QRx zRIVWlplcsCJclzXgVTU+0adbUyjC=YcWJLrKO;JMb!*5azoGA72t`;D*dmEKw7H8v zzX0Uq#5g3gCXbrb&OSH3j54syRE(PV?&uqvx&;FzsLA^j1k%zkn@+e$f7grEP{|3^D zNOwdPQt74}q<`MBrzYY6J?H4&)r1ZQOzu<$;?q@WP=u*~NnZOZz;ovrjHb(lMn&z$ z9Hr+(&1@?}Nu zeW;){p)_?{Uqah1nT6|)iC5n@H{;4^9keCayF1a$k6H$v8q0!)YaFFyH9-Q|hV=-0 zqAo{U&}Sg_>84Db7{#b%&ujJHZ4*S^ETue8*rBD~MutlI+y0+OC_k7KTcDHU*WO|8 z(RK-(NRI#j1usFGu#@^kz@|b!`dIuHZaM>}8him0mqS<}*c7NdlJ5eA{l8gVXxn0g zy3Irw$D(!Y#Ny?)DS#c$4LF;^m%3q~PrvIsZ)Br0uyQ)&G}=&=MVDaTpjvnMJt0}K zp3xO-I&a!vaH0p=j44RVHVl{@a0#=VBrTDY1S`(zBrO%K`fVwN;?9qd>zDh8TEm3D6$U}78W@qF*8FJuV=hCL z8%zK7pKpPO)W z%x)PBGPy^bhsO6i=05;?yvvRI^`4)HQ;ZYyAW9`Z1X-Zy*5L>n8G>+#mscd*>^z4G z!x*cAw_Z|?*(tlohkZ-5K3nK5-W6hi!F~UgC$8_|4*V)NnmNAHV3dSrx+X_ws*gN4 zqPrtknl;0TPC20x=-p{_9RFk1*omI)L8J2j87vb9d1py@E{Oc!CnaBi;)cn#=MXl* zsHLpYrnFC$yGd#y#Q@Pc-5VUFif(#H#0j@JFTTf7>RjMw`3d3dR~A@gz7=-^Q2`jDMrad&N*|vDsaLGOnS|(thq{(9h;oqsircoo1 zAjDJ{V@mC`4T+}rKp+oW7V&CZjQcenY>j>P7(Yt=m;7d}Z=*2QK{Nw~o8Z7=c}a7{ z{wt~N%Obou1O*AmHst^ki=ZN&a})nasdI$VmEu+-w+Z-q>`$bb!n=-#7)AX8WsE&I z_A-emp5V}JrHyxMu^~^_EXg}QK}mTYN3(-!_2)(WL&qkT9OZ#KsaE8&MPi$8LBb4T zt9q}bmgGY9ap&aG;nCng^XqvYr)Atzt-$eoqWr}~2|O+ft!C?CQjpkau2T%6G#s(< zj8aVhb{5G{ard{Rcce+%QPJ?;zmsSLzKF5HAd2|;LLeIvV+(7nJA)i}y7bvNM60{$ zb@>Tvt@<4;u(QaY7_Ci;2(z4t4mxbanb?!^2DbzAt@>5!lF!sxSeyuU&1M-Uv*)~Q z7_Bk0RuepkxamwHF&-8Q$&lo>qeJge{8w1#BADy) zun&eBmI=y9)cq%z&=P2=Hr{Z0f5et4yzM-;_P3sYlC40$J48L}V_)2ont z-^`+QrAUig*DV-c?YE~9-TjI9Lqt^d@J2L-pgvH#xCT*ko+JKwlvAp3tJHBNgnyM4 zx_`mux=VX!3#uE(-B0yTCQlMfJ}^i3SfT~e=XA~v4>Wianm{D)iSuMEEJB_YAf&MY z1UH*Dj%=9xP6f-rj$y0-EmPS5cnIHuA{mLC`*lc6>z&sbf!Kx|3`G6@2Sa*RmHMql z3Z?3efv-bBE_l$qL6eKs_Sapo>}W}hTs~njX?@Xq`RU-{v|Sl&9|^jrSI^y-iCz!o z60Y;AubYLa0QNPUk=z^IRAp5vC_cZ6$A*{Fr&Jo;8=r2hO{0+<1H1`tHgLuQ`|f+s z`ZMS6cbiedi9J(jddwsyvMC?pvQzqceWJOmIz)^Wkx3p-oT<-iI3I`{I>x*5im9Z<+;pfb8SYEF1obh)&C-b=#V&0bf%rntolnO}f1 zZyY?dTIRp%yc&eqRWSE{v}?9-0zzgn)9gNWJvDghDs$Uo#Ygeg6uan&sApTMyl_- z{ONm(<=>i4F)s~MF~g?ASdH@cg+mL+Bi^H`mbv$pR;YHefvkEiJ2r4dk8s5hm@r#Z zNK=Hnl(fyV2%1?}Zp2gh`-?wnlS+rK7iY5ap(^&YJb1oM%CR`BlhFGn!Q5A$q&jzq zK3)skdUrlxF7iX)rPfSqHW<}$7PQBEZh7j>n1y9BJbSsXmtzn^SCec!MN!h|qK_a- zAe3GD{3EucS{t}f%Rvn_fJfC?dKnL0OBIL)Z%F!}>c|kJp-o}s^Tkp*TgS3LBxEJg z6edA6J>xcy4`B%9XPeB6VeS>u(u18i`Q8b%CWLSBCgQd?Tl=7P9*2#KbLXM7S zC-sw*BN&g3fg8&9)L*e7!u$eb{|q*~uU~YZ6ZsOTcU31JyMLgZHfbximYLXp-X^(w zbnQFH*e4^HBTM0|g^Mh##;=HQw8vV*J&-+JZtQ4TsY0()Se_cNEERCR`<|&`fZ7)3 zU`dBApP@|j%HoELF8eSv7ksJ4GvZ7oDaNZng)#7WPAgUL%_tS+Sdus1v4lXfVE}|K z+VRU>9B(?)PhN#bp|x%Xvu76gty^FI3LF+g1~x~_tfQ1*-39*J8AFf%zc-+$_~{u$s8NoWI2ajEc7zo6M>BS>YY-x9IVaOd zw@(88LwZd9)U4E*fAusj_J4^QtP|Y?H|Ce8fi3QM1|J}o67uvZ_6;8 zprUc%{X zOm$?t&S8@GI3JW<#MT^0a=g#8|F)1(pWmRx=mekYbP&i3P;_i?9pC7<*B}oX{ns;< zXL~#8+~(7mWE|$;l$H_vIM*+6D@IMrU8^6|9V@!<2yb}6P3Wl=&PRvjZ2vAHOrYY> zWCm)Phd8oKq8k;fp^-e?kUYGQT3NrMCDA@&a9ZiP0Z~ANOQT*M;=SgzXa0Afcb z$e1j!$hQna$K35jw12wyMmc`{jZSDnBeixt0(xluo7mL9kIN192XFO>FS4NT@Vy)L zEFyJ^@;>_itVDRwg^_^v+Q$ItL**bF)A|4a1Z_c@^pnCKOr`{X^B|-)p(ZApLCZrO zj1FZ5zxMCT7>STU`7G&+?dB1uM{!zNd)1`G$P%Y#cOV}b#g+*bYjy2ry{u_0oWJCbcg;Suq?_u@a+k@-ke!RG z#J+lPM%SSBG8`wg#rg1dK!P=D>^ES}Kv8K5a+y_Bj|}pf-Q5%!7<9VPz;{~5GB_*e zd?*7uJb?D=FIe~U66HwauF)VzHZXAq%&XlM+NXj4Oj=j{f>BhotTgWi9E~QY-}=Fj z6do~WY|}8=elZHVwln4}C#VbovHdzdoBvER_0{Jy>2aQ1c<8a4yAjk#sdR23`iN)P zB;te#Val|I$BiK8rB+7Uv0srJH5-8C>#YY9+6ixB+*YjHFkFjq|7nM23 zY$^!=<4SH?W7h@X%fYHnG=;vmjXr|wZ2Ri(D!F~|aaixB45(!BgJr{cd22zdYv7*c z?Q?1~@Lrjy&uoyX2U;F2Q>K%&XguXyj<28`9340ven94W-?8S+N+ku0AVSG*U;03I z?x8Bp#1h&dDp&>6bQDF%17wc>Zzm}sIZ(Y-5lSaIH920-I6|bkrXaT*C35k^}q!E$0 zFbLDCZ)~JT`d@}WuAoA8otqMTt;!+=;`upQ+X>ed-#AL9_Cr_R?g}yD=luL;k@Iyv znnLLa<%3TpAIm5K!o9lNzAu@)<@YK*EwoF3ryLwIR2vr_E0Q7Gh%p2mQIM-~HhUQ5 zz1r-8UBK34y@O{QE#=3FbM~#+F^pgcv!HsYU56p^Te=&lQhK%~0H;q#H!YiCpXu(2kA>t9j(p(k$ycCC$r9vO5=8wOS zF&Z4+*<5T*-a(Z#kOq#4Hg9TC*&|DEGf)h;NXLm=Z>7$3g#e4`I$YPWgWvTq))PJe z!GZWs`PDvuM-xp-1xGt4FPR!TTBQ+_)|aH%hlmMaXmZ0&-Gl_fu>e=J%mAiDD8%Y)X-&0hi*EvwXGFLpg z>{$y}Jih@3p`@GYow|;L4vYS%DEx74-D?OPe=9STv7O}O%72L8k&d#iE#^t7KW8!I zw~m6*c)JIomn#Vd^_>&p(0K12S3~%A;IDqR|HLx`@NL4O5&rH9Ur7Xg7bZ zT6_VvlU(X9Lr&qWUYFuXa7}RLOeVXp*p5bCJrMV)~SU3hhunJ8uq{un)P z>g3ShjK$=w4IwzaKGoB#i^2beeKSlbXr7>1Q8SpXaMxK}iy9(~Q%>}N-55Zl;I~6! z@%8`!sVv#DHXG8&i?7{?7akHIJj_N+I@GB%9=9;ZUa;bcgDMe+b$Nm6c4^b}+nKO0~|J zTU4gGoRD;@1UR~{uXj+dM#w%#_;wx9kb$UO68rq~gR`)5 z64QRd0vxI|H{@BnHS{3NiS>?HZ@sz06_<8$CJA2PeN2e=xV$EvCYJgPAtnaUBc-ZL zsCC5`0x0ctv0dJ07!g;TBJ`4aJeL{ShV;*p|DX$uBCbMhM}}b+7|(*P;NwJV;GCq* zwHGPCs>qiiHHf8W^6UdLe>$U!)cO~^m)4(aJ$b`O#q|6c9r4e{qHfSk%W&yS5LJ<* z(0uSKmI#L1;p?Cs#TyA|hIe5P##+uiZwWnSJ!Wm=2Y ziSAqL=H9kWwqSHdG*SZEfp z(7+QJ%jSq$yR5aeesA&>ka$P54hYcHKY6b9xDA9xF@&O>jFRM3oauDt1p~{y?Qp;} zjdMFMPVncZ0cA(xRk8Wjn8iGi%Bme*fgh87)lfoWMrUWbh{DcUpN`hJA(LB3iemeoI z5&N(LFNca_V$ahUBMZP9)Ms-(OUl3Qw$`2Qur2V0p*7X6;j?Gm0|Ag-lCB6tW zKw{gHJ{;#gX0MV*&x-|f1MU~L%tr&UXG^v&5>#`>)>yVBm)EzsnQm6y*cnu0-Fdu@ z{1QzEvZk>aPs9d9R2RB+E)UdNkOn`<6qZ9;4#&mG0av%9?|ze;r8S;HtIOcvc?Ks? z{GPG~9o)&Lmu-wZ_HF?JA7TFK4gC;iZ$hYD+_G8TH&<>bR!$*`LZG+{EflOU&xt!b zD4`_C;37-G%XeDERw**Dcv&~+_@C&fu_=0?p}{0O*kxxH(r?6|T7?y;2NEo5W})Qj zy_2GXKG`5^@8$IV?6}78%cNz>uz+!W1B2^CYyE0EXfaS^0C1jv?%4)Ks#`=+?u}%} z*ucHoaLO6&8#n>wk(#;&2ON2dR!;#&+cG3Wj>*GVG+oJVPJjSt9;_(0j+Wf1Vv05DX*Wcro8dv~aXS18x1UadOl{t7 zi6Iu|?$AE7OkwCW z7{k}IW3~8&NI7|yr*`zD?1D16C5pX_Nt5P$TY(;T#w}UHJfLMT&c-w|{T892vlp1P zfCGxuK~GWKf!-tI-;dCu$0?1MV6=^Px&}u5UJ1-{k!zbb-R@?gAzk%FdxxA{ycEbg zGreW7SsA=)3HRrYK+&ycEO92(cijxQv9-G`jZX&!=mk%?lbxsN$Q~xNXmk<pP3@>a8oPt{=x@SzS$uZ)4SALcr+|&)Z_#Sg9GQFj`F03M$^(mbgN}wMhX=C-fd*V@$W$u%s%4`jYuA{ipKZ0=$VsY;&{+7ZD-krN z^pz>#D`sCY{1IrnvH}2CBazOl3uTM2a!tj>jC$O5wirJ?`?+96PliSKhh&dM%!)9E z_}TS=OJ+Q6N^K+~FpDbXW?KS!45h8Le*X~KD8O}ei^NJr4{V^vPO*8^3@vwCw3dn@%n~kq!8@UHAb?a&qQ5hL;07aTCL@(gWKHVt>h zV8CmXF2lQL6{>d4q+t=C!mOxh@poAb!2CbTh|#8GQ)zns{(7WqmA|&;D7A$|XWA+R zh8b4JO$tJLYzA~bTC>*n|yv9k3S^K+h!-1b_qUhIz!Hsrn91`)3v*(GC&Ym z4?L=tZM%~*HZh8WOJRAwKKe=X%-B$!D`~w2yczWUjRp}dx8?LORKLqxD*}t%JY zNPOqF1BLf`L*d`-UFoT=)Bka4iN+MtUq-Afm)*k>paP5%2JHtqKV#C;@Q?l$dyIl} z-`$E1BPIi^$#V$&i3<5c0uS8nuWhu0oBQkD&#M{$TJ~eM#cx9j-cu$)37Ry5sP_{k zMPRW%(=$;|l0B56Vw=n83Ox}Q*#+?Kucm*3eb;J}3XX$$x;RXhBpoYbwE!#jeFqr{ z14p87iKsF-qcY{Y%COKwyJFitfU;8mLO7s_*! zvq%UlLr}F1STRu>0gvAQ_Cl%UWNR%>o}4kUH5-;^&`cNzgJ4+jie1Rh zCr0@SXCxZYX6jK+&Cw5j$tyMvqCGbfxWeZv8M4&j&Q-4LX+Iyk-oX82SpMnc4DRnq zU-ZG#nlS$xH9$FnK|4$)CI|!6O&r+y=DnHAPysuTN=pE-A`Wc>RoVcUKxe;1ykQ;Z zH7ji?!x?(r*2(WcaZbxDl3*htcKxmUpiA1xPYvs`^EKIRX!Ox(fY z$Jbp?cCKbQidrb0vuM`-z+{kSu<2(kuqinu_S1NK18zVYNR_Ri4FA*}YIKET;XxbM zkgmx)@!;2}K^D^I-FTP12&J$dyH~9vLvgNp*B#o|5pJ&=fM&z)R?lf?cBG=LEF@r} z`((Q+PT*xAA30TVOqJlDCmg_W!6NTv>b(cT>$11ot;JeM5bs319;}tz2XPsoIFGo- zSV`^}t^$VJ?d+>WF;n?@XALfj0g3ANQx~tou<1ovrzU>mAOw_fdXq?#eSXN!@7pze zXM~@u#-1)&%#=^fCh3wv2}eZ)h9J0CZ@2@)Na=>PLmC1F{?u4>IEWfKprCHL1WxOS zL2_VnTJKEg0%z0)s0&0RHZI{>KoqNZ*k9E*G1|x4X9X0ujK>Ka+_&Ezim9%Wb&E#- zB&jh$)vD`p@T+Y-Zx-NW6x2H(Gt(e^V5NsHfKCzDZx?JZ5q?K(&Ohda02J)qn+TLD(=$svHiUT+yvcjN?dAdQHq5lQPs!Bf%(Fipl>BE1lq!w87; zZw3#93(xv4l$r!?X5~XM7gFp3Cch?=9JC|veg&TGR~z?;BTj(Omg^fE@RSl}WHrtW z`2KT{vwJd_x?QsUnu*QNaB7H2?;6Py>{*aUE7orQD9+cfR&x zOwaw#rwVl0M?TN(tqF*KBP(Zd@1I=Zf7h`d7mBavyZ{B73;)AIrArelFbcn;GB9~f zrx9)SG*#(=G%o(j;CF$LZ;4LsTkvuXfb=&j8a7^dGt@C|J6G3L$N1kWE4j9K_da?G z?=+TNIDpAK!{&pTrTRN)vU+fhfD4(o63baiTaZ2D02e88I=L{LF{aei4u?SZftT4? z9@j8Y6S&_j@QFuD;QYJSh-?$dKe>5LO}=V)1|@|5y?k}#9Ckv`8uMAq?s8lRe87t)M_2~G6aiS#*#Dc^E`tqt z@4=+SU+ZRt+v(34$zn~C8TWLr&+INK{PwDq9^B%>_)l4OG|WNPZ3RgzRK`7-kG05* zB_GOC(;xy{RNFuSq%|_xfWVy^BQy|{f7MVU(DidY=>|Y6-t`mTSh?R0ZvZ_>;R@elwon)+Z z^)r~=8fyTo)IV$1wou=+i|;C>4tBV>c*Ah7K!3V)0kBt>3rD&6_lJ?fC$q~=_U4Sv zyUn@V{Q*;r3xHd(!iZHy;Qok}83di_I=)cD?ZcTlCe`W!|$4yF&=6o6%DiIJQ z#fH}@!~{Fkwv|)a-5MNtu(Q1}sRGWca4x0z3E_1&6h~@Rird4t>n|sgRjkQNu2|Hq zBh2oL`GZ4_Is)o>Mlub{N2?!Is5tfco(sNd9%a;iEQahqm|i1z6W$Utd-}~kChQs> z3r~n^hOKGZqlNbpcVNiC&Lp`afyzAW8QFn{oS~s4XG6I?CUeOIrd))h&C)vDQTSau zo&vhMy&Ld$LP)xZRh>9~=8c==tn!-_OO4OCAXsJz=_>dsGf5`3y3NiG zPYEEd39>DyQPeBLFE?$LO>G{5zw!y8V{1hof2BYG{cO5>KeuRW1!?%dzm~=SQsUsk zCh*&e9IfiI>AqU@T;%@9bQ}>Z=X&Nn0d%!da>M4D7#fxR4xE?V&3f1<gc>n+dvq76+llnx!rbqwtEnWt2akK-VeH;L`Z)%$TD?U!B_X&*;mr6ul zNOpo_Xi4t=^83$ig*0%jxhFkMj}WJP@w8SxIQ=z8g*fwX=YTcqthUJxvbG!{P}+S! zI?=fj+jlFr^iM(wMNRJ_N~T&;KtD3ZibUbnOmxqJg|x7I6h+AQ;kbZO`0PK9^Qnde_KRlUlE0GJD>KHC~-Iy97oePM%jhZau95SgOkh_mj zs#tm8TYusvd}!4cKdr5?b5S5%GJD6uH++Iqv-Td~$p=u$uY6y;5354$MKZ1qP>7+6 z#Fi)!afk7S=VpXO^;LK4HpB)yPvSY&N+eIek@FTDr4Nd%KXrio@9xIf!mw>>Z@}G% z4~B#-$^?=b$XHop&4XYJnoCLGlCt}WHgAdebFkqfi0K+LG9yZiDXaKW$>^l_ua6X8 zh3uqsCYE{=${Z&a|LbchW;}Y4tt;h`;FA4|N-p{HQzSc{df#0sfWd$>z&;;J&|Z=e z=+}f80tXEwpjsWxbWN0`fW+M=NA=-r%ib(WN%Uf>nTc(* z_2TPMphVuyBtGwD#_-;k2R`e<-eTIsuaOe)fD(>{wv5>I!U8_1pF&9JPHnzGI0^EMi+tc5zW#?c{3qOQR3zSaIx>)l{QjziuaP08bCK`N#k&#U40<@7CmwFvaWvD zZPxA0I3uaNc#Xa_U%)UfXXnJNm?G4VQ)U*d{r^aKwSWU~sD}SoA<@;R(SA?gFgH$- z?8;7JGs<~(?5qPWeyX^l%C6V}SHZS`0008!L7Re;`b5B{NB{FAo+S^r>-0uY0NQ0Q zvG{Cj|I&SS_4?fYA$0V~%bx0029ehqj|~KXH6Om{2icJ?C~XiNp36?rh|w?&`XM*lMfEae|BPNU|6M7LnpBs`qtG4XwMYB&uEF84HFljPo6O}x1VKDKMSCAU(Mxf7 zl#&+oUhksX$A87l@w96|u#k+P8BUTmLn?ziWYiupxz>r~mVveE3reBEQJ%>mWUa8h zPA%EJcd=O{A;A_uTPi^HW+C-+;OyEdo8?G_ul>z&)^>hIGV^_ZWZ?)Yd=t>X2g2rZ^MO z`{f$GO`?e_ptphf@h$%94C^7?Dbyace0%y?WRpCCdXhx z%+A-=es@3vkMl=^M|HxmF>cqq7=X@=ue3RH4Jq_jU z2DREiy#PcDawP(yy5`f*J4E==u3%|~F@-%{llt5%JtSwe@h-I5Ezk?7%afPnin$C4 zNj66LRQ+(0KUT*=e5q&O((pOse-R?@tq56o!#J)}Dl_aDNwc8Diq|hd6xTT9Rc*^b zlC#~s_199ci>Vj2R1Kq<&LxTn=2@5=U1$dHx~lt4 zc1^i4A4>kKNc9=97D*J19cE< z^rQF`(L&5H-RkWR4d^SS=w-ai!4Jr_Imhk` z=?{)za!QG(s|2G`T;MI{qFP9C{`ma~8ukkLAd~GQOqX&=Z`QHs(u0ncy`ad8O*dL> z{<#dQY$oT~GhBYH9yNn1l5F7mYlz}S^kuI9E33K3uwnDtWXISwKvOFTygw-n@2ZrosPu#3E2uV>;di-(6*3B?A97gqUG#}6msy%!_1S80dNc3) zvPDxT!4uF zE`e{!;UR8N@ELuxszlJe20p$-TgZzZ&+uB%rItEZnhN;vdU`U>Pm-_Giu-leuUB! zR*O|_>}fVWkHBx{*8rxVTT-|@rpfi)wKEX{-0HT-zpDhszL^G~_LBTBk>IK2X`M#B zEv6%uS)j#+MQJ-OBeQQCiTqmn*SYLRg|jDD$VIC5E8O;|QO(lR+ z2~>ri3|(p3@4#J4zHj%ZO*Ns)>D+7`+Y6+G7v=qaJC}m!Iwg|f1C;Wh{-w2=j3Z@h zwq1mfva{8BF?P_VTZT==kU>_0;nT3Ei5)%8oy_H zhlmYE+G%qJ8Y>!0esmTQL9PLGQ^;_-C0`)^8Nt*^%T4Y{j513rcxNEc=opWbfyPkR zvg-f5He9TX?VU2OmnjGURhf&I>~eSSf<`#d5E^$teDFnr^TXHfF^9gLA@7E)Yat93 ze5Y$Ka0mm!ay8JRp!rT538zIR9#gWG<;u?Rx8#%JaRQ@&?)m^G`CG!tvmF^s$Ay2( zP>meeB}A?puGda@WO9grp$qONEVPtwG1F~V%)->sS6yadccLC1Mhs^-yk7ta{B0u$ zW9=xpAR{mA)=6LYW!Rf`Yp(Au==eE2@+P#5`ungle4GNyx%K83y_|-k!lY~#-A_TJ zO*sNGm4|)#@fG&DD$B-m&A%b1w9K4O97k{y6!hz$_U&wG5-OU%PV3W%)N$Y2M$?&n(@KALq+|HgcLzyTj{NHGN7 zI*sy0kbk*KCV_9)w{SA#_5za3^7WE6?j(G*$h-d72Pgi>K%LEE2^*KSef~c8`;gMS zB@>oYFCQa^t~{{j^s6x1-uf+)uwqZ~>~zPI9Wk?O&2~>0Q8>YbY2_F8~!Kt9QEjnm+jvA=`hfGqHRCs@2!8=RZ3#G<{MjTxX`xoIQ9D+U;p)9@WAWe};a{!DuY7 zGO-!LTX!*GW+{vaUfKs*@2Vc<@yoYKy|EFMp6E^Kzh% z-Fk7d)Cy+$4Np%K56*0|d!hF=2WF3}>dA|F-d7lI9CYfIjMUJc@YQv8FQ z67k`?4N5Gi|GQj*WwP|(U#)n#loRxt#U}%$F8Xek*6P9ubI)8vim#xN8(KF%a$Dd& zgsK>b3%Uf;*-g(;7Ho<5&LOis;RjNYP;#kahf}@4UptIaBScT7AkB>WyHH=gpJHWx zXf&MO-4r3X@V9yKEycG{_L@PhJDDqCj71m7U_J8k8)zWb-Vik_Aepu1( zFw25iBVsD(SE2P>BHgw#!>LLtvaUDW;9wv+l$N*^L&O>?DkcTcvnJp)r z_`$V2AIT0*KL@EM`-!{&nR_I9dJfuOR1X=GH#g)3~pD;O2Ogz4|uKrZScYg9p{d1rCyh_Z>|K!h)Vq-UQfg zCZAOm7hjvirmp_-Qp-v_iO@eWrYk+P$qj28&}?Pm7^_fm3VfF#F*0M$O(@4HCwgH$ z2;ORj8{oqm!ufqbSt3?f9&Nc#$C|K48u5HiGP(Hb<2euEHc@}O0|nJ@+!x^_2HpxX zt)w*H>?spuj*hd06k31Gubo;!1l`uX6lKW;Q$ z8GV;BVmo4j9PDcFaCqp?wUHo0<{T~GfE2hDDPQaE+)PH?#n8Ng-;X= z&9&KD|MlrQ9Wk)Boxf%vib<_Sc*JC{MNx-(k-QK0S`ms!Q)Stl=&r=_5fnX8!fR~N zb3+CgxA{%y(Q{wF4?0ibQD8gT`mp#7dYsz#Csj`kXILh`ofHl&c)_996}r2{z@u(j z5pY*UdJX^p1am=~=##=8Or``Y|NMjjUG#7F^hxf#1qixvT9`p?R)D{WWP<7dDlL(R zy(yW!UTU{Ujao~t_-ZaajPGM&oW45wx4|q{2b7(bIWnZFLvGj}%jHlEA*qPHAIauo z%yw;Qe5&us*h*uvK(>abh~>y>7qiS7>+GG25}7J(A5uE)Az8h)cSC%kzks~NL21;z+<2QsUkFjRWyXs!>TMlgk=mM| z|NF!bc8kmA)P&8+eUf=eRhYhnx!Q{aSalXysoscp>q)Vj$w}tpY@e%bP=U8G<&PS~ zcOMRiynRjuO%2lhUray~t-*^0Vv@Iuj*78VHv@2mCM_@#W1vI$kBYZgu~fRMQlEbE zX4#|b6lpF4*Y5+xEu$E+)JeW(1Cs8N%V-Kzh5XHKVDpiii9zj6s!@X?sKUf))@kE> zK}HD6&41yxj65wpj#GbHnYpWZa#N_1!;S545M6VDROM+S_DUKc#hu$LQ9KU};UrZh zoHbtpXOvQaBaO^LIzAW$Yo=ZRk4n|{fgffEO2+%Lt6JH22_uH`nbeHx;SVc%gm+1+ zq0EO3JNl)ET%MdhR4b5H5LXfPK5IuNNMaudjeN#vW=iLUpz6~_(9e<{|E=l@eA)#l zdGBJCMGhlAXg>nLRobSR!)?freKt`-@4bSxQPt}?P36SrEen(Rk~xK2%IZyWRAhjg ztx^F#OmrY-Q*yp4^}1@-#W->$o4jbdzP5=a=1n;ct+FAJY>Zg+^cqR4t!m19E*~+} z>nt*A(5L4vw1r&eG+Za^%np5qt`VW>_8-Fu>YpTz1XPvxDh)HA6C)773R5_k#)D&y za<=e3CrG*>u2YsI5Irk=@f*-QyrrKu;`p&{ox+YhuFwCQDFlP|LT~L#2EYxBiYw>P z!1UOGX*Rv}La|g9>)BPIKS$cb!|e!I1|%`zc&Yy#iZvr0sGxUa&k7;*mfkB++)Fk4 z^%Pt0p`SHHcw`iS0`A@aVlr7(nh92n`S?_n5t1<7oY0RWXuy7FRHl+tzJC;1+wnTN zS&p|1r$r~Jgq@|gE344A8HWj8Hin2fvcVsmI(sXkZ`{8TSFkN0DW#YKa9I$TTo*#99q#(nArf(e*BBYlA$=We`U}NDvEt6#TechDOjbi@{Y;{6o6cE$~vc8 zagY7AfiEtyIQ=!8qIbeE0wIp;EKrKju1NzzmdTzAxO7BR#zR}e)pSDy5mxJ0jvQHz zuU#JDDkCBOJ*UwfAM-X2Db-o-z}|jdvj(pR2iIR}D$D+H-5@s|OYJ6yE}ImplaVbu~DsoJi3aJ z8TtKiFaQ7tAVHcAlj}snm_on&gahvA2oK+^%_;y6tRJo8nw$1Q$yBGxAe;l?pk<*~ zYEM-NbU{50&~`zB$hHNWNBfgVp6NJEdTWJzG689Ry;CyYe&16g*Ezk;t%&k*|I2#ib4Eyqh3*yek@o;g!Kekj#Xx(WEu z8-3Z7_uL&wJo?M?xCA45bnIYK6{2$R4wpR%LB%-FhIC74t1lzn?mSeKl5hhB!I!o8 zkkhTAX3${?+wI)B(zu~o?(*d`#EzLlmFKif+<4|2I( z1scA*zw(IuXasD8JF<~9J-SJe@i7A$1Wpm!h{8Mk4Cj@{o`#o}oA{wk;cFL!gj@61 zuUQ=Awnt4vQ0L<7@cNR`qPojqXtb@>XuHpjI*vMg$93gg zYHb`8N)U?QJ9apE+t1CuEtt747Isxtw>%6 zvw{%#;oXUaX7D(y0dTVs-c`!=`!%lCgbqg-XX5;O!KLod+c#DKQY}5OO`e|1K}Cyl zuOml31U35nWQ!1ih8gmXJ3Nt!`;Uz}oENf}jPC2mKMvZ~30k0Nza(YfZ-pG%V|kr{ z%${hIc;XJFbGK37^4{*9bC(p9R7utwP<+27D9BLDwPX40W77zC%tN};(1;rjSutkx z(mMbexI2G~31*S8(+-fck<*Y?m?c}pDDzKd;D~pO>&4PH(KEzeB$Z`pQUXdl0$N=y znWu8zSOax$7Hx}e1h0iYF>QV`FMG+#bX8k3G5o!ccs2cJ&^Hz_u)i*frRP-g7eNHA zf4L3-v20A|JVZx{`B`g#KfpUL*!8gqX;ep=<`-NqmGBJ^a2;ZeU_I zVNPkULe-r9IYbU;bmi2?Rjcy11IWOq2Vt=NB5(5n^+ zV>g$!%947hP`HG{zxIPgMdD$&&rNMc2awLso`Z%AMnCLhH|h;fcI}t*(j=hBz&o@` z(HI%u3Jr_+4PGMFr1m8`IfrQ0(^kq{0yJ&Bl1?$^jJHM4GeY!hu+!oWgCchZS_LTq z$_(|JuUhm+J_VYL&2{W_EajNH)mUauM@BNxs> z1s^k6DsWAxhg++A^cpQq{=v7Cs$MURn9Mx|;&|)Ml}^-`f*=(UewD*OO6KVf%1OZu zFpB!&aLz65K4QN{ z)2K$OM?F!ue2m?h4WIB){0XFjiN^)#H0S^%hinWBoZ`M5`%|j}nRATsH0S@t+~Nku zBE>U%2D0i^eh-zj4dM{KiED71D1U8q#$;K!Hv15w(yT_j#wGSafj9_Zr5J@Ri|U04 ziT$#7_v=$z+PV;ug}cxfYfvD7$jg9Ef*SKM@!hreV$P)e>aO#S7*&8+*&1g{wq$+W z>_o#At_=EJgUSU;6|TCh0{6D5O3que-q&H*Bx zNn`K@%T7A{tQCSil2w`$N3S#fC+Xazr~RHQZnVXYndYp9bpP0Cr=>WR~ zFzK#{kA-jn5XL6v4vhdvssM3G!J_eV*v`!5#{XN)tf-h&cd=6r?M@M5Ju#->^;beq zemN-TIjT)tfC>4Fn5qkw+>EG-NY3y_a0X}q0T>|yo{krm;wO*C7c4Wsh%fyaMnpi3 zH+XmOV=r`-%rOH^sQ>^2T>+jd)Q|rN$6cY&A(mBUb&<%S)*L9U^Wzi&87{)Mw^tXd z$6Z9}ggZ?S&0zx07xm$nDH;4ZMwvLiV4(n#(VtJ8V6gJZOd`O@HSz{gm-UiB;BrpP zSHO7k0l^nu(zBUlCY5vihz6c-%mpU)JAcr=zX{kNHJk=ehF&&U!GUp-qdWE&g(<~!H-!*1s zs|wC#;K$Y@YyR1iiB;hnX>W2qGw_800Z2F3E0HYn;?NT6Qsr{GO^LwGI1SaK>wTIA z1n4Po{eyw9$07)r%!YIUv9j*Lc^2qshQoTCNTdpi8QKI~K}%SiU-FZTn9VrL8_56`Ffqu^x$@GoMFKITf6$7 zAyZCzEOetlk!O}ReGy+2#IXLhfs@uF{m8Ohn3yx;AB=MYGkx!iGHOtUn+-Em1pv!q z6dWE;V2Ve>DJq92JLMpe)mgb&EeP6_O%DKloE0;mkEi+10O&f5^UCU{k;g8%)?dfO zmA%b*Rb7&}#3jL4Xxq82ygkzW3^rUxU8b|ND!~RWPJi4M1@?DqBUgZmI`}4BGK!P7 z_cMa-?M1UgkfSL!G4f-Sh_+U8(nOZ6?cieW#MfswL3Y;cH3V&_nfXnFQ-m=NyWMpJ zDcXOM-in0s7FVlB5hUk034>A%VorG$ozBp+c#)by*&)BInB;}_LR6L242%sp=} zT%(_XhMERuw$!uSpm6$)byFTp)RW*@3rVFtofEKmY&(06yq)S>KA@!UM4| z8hdH$St}Bp+8^DPOyNj&u9BTMiHJPi0$>##6?!SD#h`%c4HWS_W-QrVWb7fdH-P6( zcv~LCX>rN2>r&;xDNd|7{x%L`^o`C|U*DzCdHX*+UUU-4A-2dN%-{p52T8aN=IK8m zd2+WLG$nG+yfOAhYB=Sy_mDDQ6ttL`8jDbKd`%!J4~1r2lP)!$zc!OyGvGH|D&BBT z6MA1a?8g^4Z{^gbvnptdgOOXJ&c0bfWJ~CV;{w`pz7`5S+u6j%V?r-6^lJvCY#}HN z=dxurK%=a)TF)dJonql{yVv)WVlNy($&e*ZZvJH6>2S<21K4eSLMKXXP8C4W=&l-| z@=0KoOEBO-CoAaiGJ!9WQCxW_s>-n)t;uQ;0_qnH4%RTy)+i5_s)UEn)S(cZ3__}0 zeejKICL@t{20lw7GkA@+dEs524Y_hiqO`Apb6Vl2VezfWYV(cE&A3l2)duKm501jz z)yas}vm05=Y?=$E=99n#lMT5Nzkt1soibCW=>Y*=rdMOdHNV|YxCV|V+VL%lv4~hH zvi4l6?Po^l-F@mTZRBK-kd6Ye>nwI(e%Aq4ce$tuk+;SF`o0Vbp9 zr2AhysMR=Ip-Z~YvIIpvJY)FcDWAa77|<7aQ0+i+rd<(>@JWeA*nLN-eVb1?pN(7j z6WF4^%kc2WOoy%RtH4k{2i|crpo1-Sy`+z!5 zi2Q0gcfb8N=we&O!s|NZg1CI!l}<~~XxQX;>=FYoP@>%zfAi6ZYyb*W-0HlFv2Tm< z!w6vK7od(;u>K-<>w&2w&=P_Z9*U!>gWs877M45;zmof8rPe8sY0fFmo-!x%l}|JR zH?-=0OeQo9Op#T5|nn9W{lfoWMrUWbh^#++CajJ5y2O&N*Fc`5OC4y|J;kkUuq{5^v$J@Jy5Di2 zlI!~xVeeYAahRzS|3`i3*FG!$k*EPPxQ0+jX|nSUZV)MZ@nvy?mB(CiS@rW|^*nK(_fHL{fH^Sf-c;5!?cdH%sV@$YUHA!j8hF_jtwAs%*_XIwc5x%qKJr7?jX3 zIA`z+0;-Ww>`5>;mQ(Ez^wqvsPYIi_+;REuIL3keCSB&;r48{qT125mQoc@g`Bxnj>7j*|A;djV1FW$D0fxlvzGPcASTw&fDr0+{E1b zhW@AHgUO`6!>MG}yyMAOpS=~hAT3tj-&!Bp;_TYNkqky=6fDraUy5g%d{mz+!$AL~ z_n77HJOf6^!3EtV&w6|j}$`CVMQ<;ifvtrhMmxv z>Sq6{8XfhnQoL$OB|u@>tgvYjY5ku~P{C_UU;c>L=5`eyYE=)#y)PUS#}PyKk8LN! zcvOAOMFcipCp=nx9*y>jqLO+|V6O-x_`?l68R8I}OT0G!%^AJ#d@A?EPKb= zQ|6Qcs?o6zU9LYx*&dBBHaK@Uc6^E=(5!(Z3=l5p6n!}VLc(!BnQA=qz#-C>&16(8 zeZj~^X~89=aPWJl0ld+=YwOSzsQ(ra)4|0Y3s}~uTLjGlCcHYfOx@vqQBRC+*%gUp z{Q)__WI$>F_vl`h2w^_JQ>K{{ewS8aJOrp)_T=xw_tSk%Ktcn|Czi^sG2yLl zUkzi|O>+oQl`5&U-G7oNmQ}i`Ga?>~r&ODOrAPi^7V64JONoWF7${jY4%L){qDzKc z)NsTid4%VBCr6(s@z9Kk1iu7MZ!%{{-TeImrf3AaaSRBK0VSRAB>q3s4~5H#SGGg! z_lmyrpEj5BQD505x}839%rM^+q31%Ww;WWa-w1DS^O-fh%?ndruNk)Z7bwW zq)GjSOn#Y6m*qHk{cUs2g~ zpG3@Jf4p&q?B%DtBZPE*bsT#KDh#Q&mYKgqN+077eS2IP!5C|`^;I3Z(DTK?s*3Z- zG7`cQ=+aRMY~gUmUWlXM!Zo{lFU@e-m>L4Y_P11zRb+T-;@EYlpw z*s{tk#3|jbx$7tkylXT%$o>#!qH46YDJ@TWO5iiv;h5Ru6aF>N5;`n0yhNzO1K;*} z{tr95TFVq9hQw|KQ09gW$b?w#5PSN)5i%7u}c{iBB{=oCv%Vh8mZ!eGg(2*wLaAhZ@GEW#NrK(~`*Vxnkf zcA0P;H$&QtZjL%|$+BWbCo(g%_#fTg%mgW{6b&ows?Dg#d#jm}N*k#vmzln9MToe);8i|a1Cob(sy|NB@oJxPm zm%-7#6Z#dOL}}D{FaSEdRC_8l=-2h9fE$VqsK6ND3{HK)N40azMrmnNpm`ok`B@p9 zP1|&9P4P%`>cew5ZyTN?`v=givp+k?_eYx^{}Q%$57fvfX?FjnWsXHwwfVB1y$%c* z5d-EkXJeYX)r>MvDjKG-Phz`Fv)*Fvc>OKcTHBL&3|)rb;&G5xdsp2IKt=(TiAO)e zp3wq`;=aGSA}5!6rm{j3>g)3`E6~U1le^WR{mXo2I;o2wm*k5LV5$a`E9Ajb)1fG> zirWLFn)47vpufXYK`EiDM3c_VP?inXSpg5JqsaiZELo?nd;V#~QnVosp2>NMw(;`bJCvpoBRD(S%)5oY>)Mk0^@yJM-%K%XT z001~ano^U(6r{>vLVx;y)rJFZq!w8dU%AL*44#{b{+j2*1l^x78(w&-nq~73&|V7a z{_EvS-R58b00dh>nsk%WsW2&!pZiU|oYZpU^r+4Mpl!+kI}&@No-Cl-g6$jMPV8`b zd+2kYXb;pVg8Y)&0lVJ|N>8bD>jW@?(|vG?Ye6J8-8{m)wRCco7(Kjo=QdR!qs~mm zpS1$m0R=sJE81K<7>yrHr6AzL#|HEbSYFJ|DRN-vSm-aoTrZvr)fOk)$)%gUwTz>R zIpwPegSkmuTs@;6?6o0T)Ew7DhsV`3>~r=Ii+P4RV}E+Q0Lw_#??}_4%9ZrJdJuJ1grsRs3~@(53}{z^1PLziP1Z0IWLU$Nz9c@9ngjA?)W-bT82bcHvI=51+aeN)l-MoovTn{ES7o9 zNr;3xd)Kkg!jzPRCM`I%5_d@6P7meqt?cM-5D_6(+HFSo(0PQ6 zoA+V6)O0!M4$ja)Q+)l1C7JcbPHd2+%m=x|;p{{xt<#uH1jEA28lY;4PnyG}Gt6AH zD(D^HL^AHn31#Fjl#Q{;W;YD>@xg61QW~59l&nCrX;Xu1>*VmrPUQ5pIc*Xbi6(Ck z_z^-_ZKiOC2WX$LK8$NHo$5@}DU$0@!+0o7`Sugn*?Gw%*bz0@8?=Tz#^c~mJQ=qZ zCkMf7a*^4$I_oX%#E(HFO?R;*MR$OPimn7##*AE0Ebi&(xX#BLhK_18U+ZHkGBCl; zFk?|!%$*`C>i9F7RMaN{`Ws13K`=cU?5)|JK{$!{00CG=tI=sw>J@LYrK!M?I3E>7 z;+iK4;d$u5G6^ZpyZ{5_z*N)L?22D+UfJ=2Hxo#7pwp9P8|P`frz6^ZXP)?P7#0pK zE=3JIG`Imuj-GzCO#l99g;fF|>u&hpCeBD?cd>7q*7n}yC8iV6g}Po9g>I5w znI^DGETR)C`KausALwv33KTeH&C3u)uK32|4q=1bAHe_s0_Z`SmXqs5!k9<@^Dd@B zC7glO^Q4UV00P<5%eJaL7tkS0n~-8pGwkr_9Ip1YyXOlU5?S-`&jz}W4FbVvWA?m3 zl{KL_JoVUcWGT)B_DCJE6~AB0gK=<~lMOSNWc(;ooYhQt4wnTYL||I-QQcZoSSnBO z=YssiI$I6_yqEnFPuYCujm7IHZbhY>+27_F z(>ymRg7eCaGuk911Snj&QW1>)MzN?NSN-^OcuIEiV?`-2_+jbVrs0KAW7gIm74nab z-xS2$E<5FrOo~#IyFPuqU-e@|OP0n9_hj5aYAJ$btqgyMB=6hsa;KNcT1t^z;Y&mGA!;>5%cn39)P+jFMn~>A^7Sx<;_8$!XyRsbeLjvm12qXRXghF^2_-v6q;P6Jj0fEV{wMq<+yIu6~NnmU<*UW*|B_c*sfMSdqI>aq5g`C&A5>c?W88Nu|2nM0g9*|E?=A&7 zY#s>33w@S{Abh8Xlv4)0q2-Xxj5vz%V+lNs7{(x(&35f}2fCDQNIqwB#9;JIfqLRG zz4kDk9MO)@98`t#7uIFeg_YpNZ7yA_No-eiDGtRemXqSJn!dN5WW>k4*(M?FP4>8O zq+kF500jmH0mOg+00=HYh^_&D{`DvL6w|c~OW|u_?bNqPFwtWNxfXKQKLYp6v9Dv!gbi9+}f@pBS`fC$UR&DNKd<6a^Oi{S>`eUijM z5O3_f!wyyk-pgUBaK`gS0=xK$Uqa&&=Vx-qyEc z#2x$m!lBb71U!CwPZ@V60FnR&D6c70N+q-3rv`l@E}*qX17PJKQpj{3BfSwUNpoHU z7|TO{ttYlXo4RY>Vj8(B_&+qOt-xJ*g}PTRcYX;7$78!=$#rF#A-gA=fbcK$N?8WF zy;Pj5xcs3yYf^OQSXblp_P@U1Ex84{k4VA9@Io0QCY7R-OENU*=Ll(lT|~~=wB^17aw`n9vC$gtV6Z)!4ZrASi7Uh@qBO)G zK3Pl^CaW(BH>XqC-9?l=sW8_kTM`RKks;e(qcYlEsi}OS+$~FXq*J-=>E1`|0MA{w z?UPkJxl673ofc6rL!CdueNN^Gz!`OoGaZ*~Op1)zSV^uii{9F^tR z&9YtPk@Lp<A`>%que}TSE_Yx;i03CtefSoDB2E0_7 zS!}Xi13rd!x$MIIN6E={bG_1Xt9IeSq=cuOmqdl#(!NH(C0-_u{83PMk(du zti`x=S}fOgf@JsJgB}5rPD8UkvS6`P=m8|AK!X_?7Ocd$p$n>2m`+1gQdJ#sChd!9 zXL_>_NmpVT7h<+73=k-p-=}{D1M9*2BOj8uqyY|GF&02=ecNy+$wo$|j;RGxVW(7O zomRz!Nh}ajUEL^Q12}24^aU9LtW6}~gcN|volO!Wln97C`kdEKxqZ^rwJ@ImqCj20 zjcO%>YpfF4G6XQ?30a&2kH)szk;&xz4Mvq^xPu8wrp^vcAVS8XA~t+Cq^FB_;NqC& zV$kP@&a(>tz2LPNxWD(#L>@xM1I1LgX*+Yi9NAx0IpTiw$BBC$`Kh9E(N0{0{k+=MUl$3H--DUSB@5)~x z#vYU;a|ywn_j;*uo0|~wASLDd4=nyHDDaP1Z@PpMr$312Ny-A>1lId;nv!Z~HGpXc z%9M06x*og$h+r>V+*pvkdeK%G4e&p8OgmMl1;!(0nagES)cH`XdOQZ(2m|uk*7bV0-@Wy zGq<�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 O=?C1<{PsAEpP}ehnp7Uz!e{tJ5=Kneh{^Rw9bD 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

tOa6r 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

akOB%FZ2~0YuYmDh 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.1.0" + "jspsych": ">=8.0.0" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.1.2", - "jspsych": "^7.1.0" + "jspsych": "^8.0.0" } } diff --git a/packages/plugin-video-several-keyboard-responses/src/index.ts b/packages/plugin-video-several-keyboard-responses/src/index.ts index 6549e2e3..4360b64a 100644 --- a/packages/plugin-video-several-keyboard-responses/src/index.ts +++ b/packages/plugin-video-several-keyboard-responses/src/index.ts @@ -2,6 +2,7 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; const info = { name: "video-several-keyboard-responses", + version: "3.0.0", parameters: { /** Array of the video file(s) to play. Video can be provided in multiple file formats for better cross-browser support. */ stimulus: { @@ -95,6 +96,28 @@ const info = { default: true, }, }, + data: { + /** An array of the response time in milliseconds for each key press from the participant. + * The time is measured from when the stimulus first began playing until the participant's response. */ + rt: { + type: ParameterType.INT, + array: true, + }, + /** The stimulus displayed to the participant. */ + stimulus: { + type: ParameterType.STRING, + }, + /** An array of the keys that the subject pressed in order. */ + response: { + type: ParameterType.STRING, + array: true, + }, + /** An array of the times in seconds that the keys were pressed relative to the start of the video. */ + video_time: { + type: ParameterType.FLOAT, + array: true, + }, + }, }; type Info = typeof info; @@ -257,9 +280,6 @@ class VideoSeveralKeyboardResponsesPlugin implements JsPsychPlugin { // function to end trial when it is time const end_trial = () => { - // kill any remaining setTimeout handlers - this.jsPsych.pluginAPI.clearAllTimeouts(); - // kill keyboard listeners this.jsPsych.pluginAPI.cancelAllKeyboardResponses(); @@ -280,9 +300,6 @@ class VideoSeveralKeyboardResponsesPlugin implements JsPsychPlugin { video_time: response.video_time, }; - // clear the display - display_element.innerHTML = ""; - // move on to the next trial this.jsPsych.finishTrial(trial_data); }; From 40dd99d3826718f14630484d78e0e73fb783b826 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:32:24 -0400 Subject: [PATCH 24/30] update plugin-rok to v8 --- package-lock.json | 656 ++++++++++++++++++++- packages/plugin-rok/docs/jspsych-rok.md | 22 +- packages/plugin-rok/examples/example1.html | 6 +- packages/plugin-rok/package.json | 8 +- packages/plugin-rok/readme.md | 2 +- packages/plugin-rok/src/index.ts | 168 +++++- 6 files changed, 831 insertions(+), 31 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7545315b..142a36d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28006,12 +28006,662 @@ "version": "1.1.1", "license": "MIT", "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" }, "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" + } + }, + "packages/plugin-rok/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-rok/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-rok/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-rok/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-rok/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-rok/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-rok/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-rok/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-rok/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-rok/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-rok/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-rok/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-rok/node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-rok/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rok/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rok/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-self-paced-reading": { diff --git a/packages/plugin-rok/docs/jspsych-rok.md b/packages/plugin-rok/docs/jspsych-rok.md index 618ded16..86ab6247 100644 --- a/packages/plugin-rok/docs/jspsych-rok.md +++ b/packages/plugin-rok/docs/jspsych-rok.md @@ -1,6 +1,6 @@ # jspsych-rok plugin -This plugin displays oriented objects (oobs) that move and allows the subject to report the primary direction of motion or the primary orientation by pressing a key on the keyboard. +This plugin displays oriented objects (oobs) that move and allows the participant to report the primary direction of motion or the primary orientation by pressing a key on the keyboard. The stimulus can be displayed until a keyboard response is given or until a certain duration of time has passed. Oobs are objects that have an orientation (e.g. triangles). We would appreciate it if you cited this paper when you use the plugin: @@ -15,7 +15,7 @@ The elements of the array then apply to the corresponding aperture. Features tha |Parameter|Type|Default Value| Descripton|Array| |---------|----|-------------|-----------|-----| -choices|array|[]|The valid keys that the subject can press to indicate a response|must| +choices|array|[]|The valid keys that the participant can press to indicate a response|must| correct_choice|string|undefined|The correct keys for that trial|can| number_of_apertures|INT|1|Number of apertures. If greater then one, other parameters of trial should be arrays|can| density_unit_area|INT|null|If this parameter is set, number_of_objects is interpreted as number_of_objects per density_unit_area (in pixels*pixels)" @@ -42,19 +42,19 @@ coherence_movement_opposite|INT|0|The percentage of oriented objects moving in t coherence_orientation_opposite|INT|0|The percentage of objects that are oriented opposite of the coherent orientation|can| movement_speed|INT|10|The movement speed of the oobs in (percentage of aperature_width)/second|can| movement_speed_randomisation|INT|0|The percentage of randomisation in movement speed (0 meaning all orientated objects move with speed defined in movement_speed, 100 meaning movement speeds from 0 to 2x movement_speed)|can| -random_movement_type|INT|0|ype of random movement (0 direction is random but fixed, 1 movement direction of incoherent oobs changes over time|can| -random_orientation_type|INT|0|Type of random movement (0 - orientation is random but fixed, 1 - orientation of incoherent oobs changes over time|can| +random_movement_type|INT|0|Type of random movement (0 direction is random but fixed, 1 movement direction of incoherent oobs changes over time)|can| +random_orientation_type|INT|0|Type of random movement (0 - orientation is random but fixed, 1 - orientation of incoherent oobs changes over time)|can| background_color|STRING|gray|The background of the stimulus|can| -background_image|IMAGE|null|Background image, can be|can| +background_image|IMAGE|null|Background image, can be key-framed(animated) or randomised,|can| prompt|STRING|null|Prompt that is presented above the stimulus|can| fade_out|INT|0|Fade the oobs on the edges of the aperture|can| experiment_congruency_mode|INT|0|Sets experiment to congruency mode: experiment_main_task has to be set (0 = movement or 1 = direction) if this is set to 1 or 2. The congruency of the task does only apply to coherent oobs of main task. If this is set to 1 the remaining oobs secondary feature (the non task feature) is set at random. If this is set to 2 the remaining oobs have the same direction and orientation|no| experiment_main_task|INT|0|Sets the main task when experiment is in congruency mode. The congruency of the other task then only applies to non random oobs of main task|can| -units|STRING|null|Units in which size and speed of oobs is expressed (null - percentage of aperture width, px - pixels|no| +units|STRING|null|Units in which size and speed of oobs is expressed (null - percentage of aperture width, px - pixels)|no| aperture_mode|STRING|overlay|When in overlay draws stimuli of different apertures on top of each other. When in intermixed oobs all show up in one aperture intermixed. ### Image Loading -If image are key framed, the keyframes must be loaded as one picture in a frame sheet. Keyframes are next to each other. If the image should be mirrored a mirrored version of the image must be in the same sheet below the original keyframe. +If image are key framed, the keyframes must be loaded as one picture in a frame sheet. Keyframes are next to each other. If the image should be mirrored, a mirrored version of the image must be in the same sheet below the original keyframe. ## Data Generated @@ -63,10 +63,10 @@ In addition to the default data collected by all plugins, this plugin collects a |Name|Type|Value| |----|----|-----| -|rt|numeric|The response time in ms for the subject to make a response.| -|key_press|numeric|The key that the subject pressed. The value corresponds to the Javascript Char Code (Key Code).| -|correct|boolean|Whether or not the subject's key press corresponded to those provided in correct_choice.| -|frame_rate|numeric|The average frame rate for the trial. 0 denotes that the subject responded before the appearance of the second frame.| +|rt|numeric|The response time in ms for the participant to make a response.| +|key_press|numeric|The key that the participant pressed. The value corresponds to the Javascript Char Code (Key Code).| +|correct|boolean|Whether or not the participant's key press corresponded to those provided in correct_choice.| +|frame_rate|numeric|The average frame rate for the trial. 0 denotes that the participant responded before the appearance of the second frame.| |number_of_frames|numeric|The number of frames that was shown in this trial.| |frame_rate_array|JSON string|The array that holds the number of milliseconds for each frame in this trial.| |canvas_width|numeric|The width of the canvas in pixels.| diff --git a/packages/plugin-rok/examples/example1.html b/packages/plugin-rok/examples/example1.html index 0d7ba191..9f0a76c5 100644 --- a/packages/plugin-rok/examples/example1.html +++ b/packages/plugin-rok/examples/example1.html @@ -1,10 +1,10 @@ - + - - + + diff --git a/packages/plugin-rok/package.json b/packages/plugin-rok/package.json index 98df0534..0653e434 100644 --- a/packages/plugin-rok/package.json +++ b/packages/plugin-rok/package.json @@ -1,7 +1,7 @@ { "name": "@jspsych-contrib/plugin-rok", "version": "1.1.1", - "description": "This plugin displays a Random Object Kinematogram (ROK) and allows the subject to report the primary direction of motion or the primary orientation by pressing a key on the keyboard.", + "description": "This plugin displays a Random Object Kinematogram (ROK) and allows the participant to report the primary direction of motion or the primary orientation by pressing a key on the keyboard.", "type": "module", "main": "dist/index.cjs", "exports": { @@ -37,11 +37,11 @@ }, "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-rok", "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" } } diff --git a/packages/plugin-rok/readme.md b/packages/plugin-rok/readme.md index 4b465ea4..ea75c5ec 100644 --- a/packages/plugin-rok/readme.md +++ b/packages/plugin-rok/readme.md @@ -2,7 +2,7 @@ ## Overview -This plugin displays oriented objects (oobs) that move and allows the subject to report the primary direction of motion or the primary orientation by pressing a key on the keyboard. The stimulus can be displayed until a keyboard response is given or until a certain duration of time has passed. Oobs are objects that have an orientation (e.g. triangles). +This plugin displays oriented objects (oobs) that move and allows the participant to report the primary direction of motion or the primary orientation by pressing a key on the keyboard. The stimulus can be displayed until a keyboard response is given or until a certain duration of time has passed. Oobs are objects that have an orientation (e.g. triangles). ## Loading diff --git a/packages/plugin-rok/src/index.ts b/packages/plugin-rok/src/index.ts index 8d2f8dee..92efe747 100644 --- a/packages/plugin-rok/src/index.ts +++ b/packages/plugin-rok/src/index.ts @@ -2,8 +2,9 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; const info = { name: "rok", + version: "2.0.0", parameters: { - /** The valid keys that the subject can press to indicate a response. */ + /** The valid keys that the participant can press to indicate a response. */ choices: { type: ParameterType.KEYS, pretty_name: "Choices", @@ -33,7 +34,7 @@ const info = { pretty_name: "Number of oriented objectes", default: 300, }, - /** The direction of coherent motion in degrees (0 degre meaning right). */ + /** The direction of coherent motion in degrees (0 degree meaning right). */ coherent_movement_direction: { type: ParameterType.INT, pretty_name: "Coherent movement direction", @@ -75,9 +76,9 @@ const info = { pretty_name: "Movement Speed", default: 10, }, - /** The percentage of randomisation in movement speed " + - "(0 meaning all orientated objects move with speed defined in movement_speed," + - " 100 meaning movement speeds from 0 to 2x movement_speed). */ + /** The percentage of randomisation in movement speed: + * 0 meaning all orientated objects move with speed defined in movement_speed, + * 100 meaning movement speeds from 0 to 2x movement_speed. */ movement_speed_randomisation: { type: ParameterType.INT, pretty_name: "Movement speed randomisation", @@ -107,7 +108,7 @@ const info = { pretty_name: "Dot color", default: "white", }, - /** The background of the stimulus. */ + /** The background color of the stimulus. */ background_color: { type: ParameterType.STRING, pretty_name: "Background color", @@ -125,7 +126,7 @@ const info = { pretty_name: "Border width", default: 1, }, - /**The color of the border. */ + /** The color of the border. */ border_color: { type: ParameterType.STRING, pretty_name: "Border Color", @@ -143,7 +144,7 @@ const info = { pretty_name: "aperture shape", default: 0, }, - /** Backgroundcolor of aperture */ + /** Background color of aperture */ aperture_background_color: { type: ParameterType.STRING, pretty_name: "Background of aperture", @@ -263,6 +264,155 @@ const info = { default: "overlay", }, }, + data: { + /** The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first + * began playing until the participant's response. + */ + rt: { + type: ParameterType.INT, + }, + /** The key that the participant pressed. */ + key_press: { + type: ParameterType.KEY, + }, + /** If the participant's response was correct or not. */ + correct: { + type: ParameterType.BOOL, + }, + /** An array containing the valid choices. */ + choices: { + type: ParameterType.STRING, + array: true, + }, + /** The correct choice */ + correct_choice: { + type: ParameterType.STRING, + array: true, + }, + /** The trial duration in ms. */ + trial_duration: { + type: ParameterType.INT, + }, + /** If the response ends the trial. */ + response_ends_trial: { + type: ParameterType.BOOL, + }, + /** The number of oobs displayed for the trial. */ + number_of_oobs: { + type: ParameterType.INT, + }, + /** The direction of coherent motion in degrees (0 degree meaning right) */ + coherent_movement_direction: { + type: ParameterType.INT, + }, + /** The percentage of oriented objects moving in the coherent direction. */ + coherence_movement: { + type: ParameterType.INT, + }, + /** The percentage of oriented objects moving in the direction opposite of the coherent direction. */ + opposite_coherence_movement: { + type: ParameterType.INT, + }, + /** The percentage of oriented objects moving in the coherent direction */ + coherent_orientation: { + type: ParameterType.INT, + }, + /** The percentage of objects that are oriented in the coherent orientation */ + coherence_orientation: { + type: ParameterType.INT, + }, + /** The percentage of objects that are oriented opposite of the coherent orientation */ + opposite_coherence_orientation: { + type: ParameterType.INT, + }, + /** The movement speed of the oobs in (percentage of aperature_width)/second */ + movement_speed: { + type: ParameterType.INT, + }, + /** The size of the orientated objects in percentage of aperture_width */ + oob_size: { + type: ParameterType.INT, + }, + /** The color of the objects displayed */ + oob_color: { + type: ParameterType.STRING, + }, + /** The percentage of randomisation in movement speed: + * 0 meaning all orientated objects move with speed defined in movement_speed, + * 100 meaning movement speeds from 0 to 2x movement_speed. */ + movement_speed_randomisation: { + type: ParameterType.INT, + }, + /** Position of midpoint of aperture in x direction in percentage of window width (50 being middle). */ + aperture_width: { + type: ParameterType.INT, + }, + /** Position of midpoint of aperture in x direction in percentage of window width (50 being middle). */ + aperture_height: { + type: ParameterType.INT, + }, + /** The background color of the stimulus. */ + background_color: { + type: ParameterType.STRING, + }, + /** The background color of the aperture. */ + aperture_background_color: { + type: ParameterType.STRING, + }, + /** The average frame rate for the trial. */ + frame_rate: { + type: ParameterType.INT, + }, + /** The array of ms per frame in this trial. */ + frame_rate_array: { + type: ParameterType.INT, + array: true, + }, + /** The number of frames in this trial. */ + number_of_frames: { + type: ParameterType.INT, + }, + /** Apperance of stimulus (0-triangles, 1-circle, 2-square, 3-origami_birds, 4-image). */ + stimulus_type: { + type: ParameterType.INT, + }, + /** Shade of aperture (0 - rectangular, 1 - elliptic). */ + aperture_shape: { + type: ParameterType.INT, + }, + /** Type of random movement (0 direction is random but fixed, 1 movement direction of incoherent oobs changes over time). */ + random_movement_type: { + type: ParameterType.INT, + }, + /** Type of random movement (0 - orientation is random but fixed, 1 - orientation of incoherent oobs changes over time). */ + random_orientation_type: { + type: ParameterType.INT, + }, + /** Number of apertures. If greater then one, other parameters of trial should be arrays. */ + number_of_apertures: { + type: ParameterType.INT, + }, + /** If this parameter is set, number_of_objects is interpreted as average number_of_objects per density_unit_area (in pixels). */ + density_unit_area: { + type: ParameterType.INT, + }, + /** Prompt that is presented above the stimulus. */ + prompt: { + type: ParameterType.STRING, + }, + /** Position of midpoint of aperture in x direction in percentage of window width (50 being middle). */ + aperture_position_left: { + type: ParameterType.INT, + }, + /** Position of midpoint of aperture in y direction in percentage of window width (0 being top, 50 being middle, 100 being bot). */ + aperture_position_top: { + type: ParameterType.INT, + }, + /** Should stimuli be drawn on top of each other ("overlay") or intermixed ("intermixed"). **/ + aperture_mode: { + type: ParameterType.STRING, + }, + }, }; type Info = typeof info; @@ -905,7 +1055,7 @@ class RokPlugin implements JsPsychPlugin { number_of_frames: numberOfFrames, //The number of frames in this trial stimulus_type: stimulus_type, aperture_shape: aperture_shape, - random_movemet_type: random_movement_type, + random_movement_type: random_movement_type, random_orientation_type: random_orientation_type, number_of_apertures: number_of_apertures, density_unit_area: density_unit_area, From 75e8ecc5aa852aec00cce9037096a194354fb65e Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:59:05 -0400 Subject: [PATCH 25/30] update plugin-rdk to v8 --- package-lock.json | 656 ++++++++++++++++++++- packages/plugin-rdk/docs/jspsych-rdk.md | 18 +- packages/plugin-rdk/examples/example1.html | 12 +- packages/plugin-rdk/examples/example2.html | 6 +- packages/plugin-rdk/examples/example3.html | 6 +- packages/plugin-rdk/examples/example4.html | 6 +- packages/plugin-rdk/package.json | 8 +- packages/plugin-rdk/readme.md | 2 +- packages/plugin-rdk/src/index.ts | 197 ++++++- 9 files changed, 865 insertions(+), 46 deletions(-) diff --git a/package-lock.json b/package-lock.json index 142a36d2..b38ec6f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27993,12 +27993,662 @@ "version": "1.1.0", "license": "MIT", "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" }, "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" + } + }, + "packages/plugin-rdk/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-rdk/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-rdk/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-rdk/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-rdk/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-rdk/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-rdk/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-rdk/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/jspsych": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.2.tgz", + "integrity": "sha512-R7Ve/Gl28PCEGLN4u5y/FA9fgVquJuyrPMxsVMyUfVtGZK2LB/XoyDbln9pHvAkJFmNcOS34kKnq08QbSiOk3w==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-rdk/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-rdk/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-rdk/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-rdk/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-rdk/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-rdk/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-rdk/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-rdk/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-rok": { diff --git a/packages/plugin-rdk/docs/jspsych-rdk.md b/packages/plugin-rdk/docs/jspsych-rdk.md index 7434d9db..f5e88fd7 100644 --- a/packages/plugin-rdk/docs/jspsych-rdk.md +++ b/packages/plugin-rdk/docs/jspsych-rdk.md @@ -1,6 +1,6 @@ # jspsych-rdk plugin -This plugin displays a Random Dot Kinematogram (RDK) and allows the subject to report the primary direction of motion by pressing a key on the keyboard. The stimulus can be displayed until a keyboard response is given or until a certain duration of time has passed. The RDK is fully customizable (see documentation below) and can display multiple apertures at the same time, each with its own parameters. +This plugin displays a Random Dot Kinematogram (RDK) and allows the participant to report the primary direction of motion by pressing a key on the keyboard. The stimulus can be displayed until a keyboard response is given or until a certain duration of time has passed. The RDK is fully customizable (see documentation below) and can display multiple apertures at the same time, each with its own parameters. !!! citation We would appreciate it if you cited this paper when you use the RDK plugin @@ -15,10 +15,10 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org | Parameter | Type | Default Value | Descripton | | ------------------------ | ---------------- | -------------------- | ---------------------------------------- | -| choices | array of strings | jsPsych.ALL_KEYS | The valid keys that the subject can press as a response. Must be an array of strings. If left unspecified, any key is a valid key. | -| correct_choice | array of strings | *undefined* | Array containing the key(s) that are considered the correct response for that particular trial. This needs to be linked with the `coherent_direction` parameter (see Examples section below for an illustration). This is used to determine whether the subject chose the correct response. The boolean indicating whether or not the subject chose the correct response is returned in the `correct` key of the data object. | -| trial_duration | numeric | 500 | The amount of time that the stimulus is displayed on the screen in ms. If -1, the stimulus will be displayed until the subject keys in a valid response. (`choices` parameter must contain valid keys or else the stimuli will run indefinitely). | -| response_ends_trial | boolean | true | If `true`, then the subject's response will end the trial. If `false`, the stimuli will be presented for the full `trial_duration` (the response will be recorded as long as the subject responds within the trial duration). | +| choices | array of strings | jsPsych.ALL_KEYS | The valid keys that the participant can press as a response. Must be an array of strings. If left unspecified, any key is a valid key. | +| correct_choice | array of strings | *undefined* | Array containing the key(s) that are considered the correct response for that particular trial. This needs to be linked with the `coherent_direction` parameter (see Examples section below for an illustration). This is used to determine whether the participant chose the correct response. The boolean indicating whether or not the participant chose the correct response is returned in the `correct` key of the data object. | +| trial_duration | numeric | 500 | The amount of time that the stimulus is displayed on the screen in ms. If -1, the stimulus will be displayed until the participant keys in a valid response. (`choices` parameter must contain valid keys or else the stimuli will run indefinitely). | +| response_ends_trial | boolean | true | If `true`, then the participant's response will end the trial. If `false`, the stimuli will be presented for the full `trial_duration` (the response will be recorded as long as the participant responds within the trial duration). | | number_of_apertures | numeric | 1 | The number of apertures or RDKs on the screen. If set to more than one, remember to set the location (i.e., aperture_center_x and aperture_center_y) parameters to separate them.
In addition, each aperture can be customized individually by passing in an array of values as the parameter (see example below). If a single value (not an array) is passed as the parameter, then all apertures will have the same parameter. | | number_of_dots | numeric | 300 | Number of dots per set. Equivalent to number of dots per frame. | | number_of_sets | numeric | 1 | Number of sets to cycle through. Each frame displays one set of dots. (E.g. If 2 sets of dots, frame 1 will display dots from set 1, frame 2 will display dots from set 2, frame 3 will display sets from set 1, etc.) | @@ -67,10 +67,10 @@ In addition to the [default data collected by all plugins](https://www.jspsych.o | Name | Type | Value | | ---------------- | ----------- | ---------------------------------------- | -| rt | numeric | The response time in ms for the subject to make a response. | -| response | string | The key that the subject pressed. | -| correct | boolean | Whether or not the subject's key press matches any of the key(s) provided in correct_choice. | -| frame_rate | numeric | The average frame rate for the trial. 0 denotes that the subject responded before the appearance of the second frame. | +| rt | numeric | The response time in ms for the participant to make a response. Will be -1 if the trial has timed out without the participant pressing a valid key. | +| response | string | The key that the participant pressed. | +| correct | boolean | Whether or not the participant's key press matches any of the key(s) provided in correct_choice. | +| frame_rate | numeric | The average frame rate for the trial. 0 denotes that the participant responded before the appearance of the second frame. | | number_of_frames | numeric | The number of frames that was shown in this trial. | | frame_rate_array | array | The array that holds the number of miliseconds for each frame in this trial. This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. | | canvas_width | numeric | The width of the canvas in pixels. | diff --git a/packages/plugin-rdk/examples/example1.html b/packages/plugin-rdk/examples/example1.html index 06aa8587..408e5618 100644 --- a/packages/plugin-rdk/examples/example1.html +++ b/packages/plugin-rdk/examples/example1.html @@ -1,18 +1,18 @@ - + - + - + + - + diff --git a/packages/plugin-rdk/examples/example3.html b/packages/plugin-rdk/examples/example3.html index 72235d18..80fb7d16 100644 --- a/packages/plugin-rdk/examples/example3.html +++ b/packages/plugin-rdk/examples/example3.html @@ -1,10 +1,10 @@ - - + + - + diff --git a/packages/plugin-rdk/examples/example4.html b/packages/plugin-rdk/examples/example4.html index c0f26b9f..0ba79ee7 100644 --- a/packages/plugin-rdk/examples/example4.html +++ b/packages/plugin-rdk/examples/example4.html @@ -1,10 +1,10 @@ - - + + - + diff --git a/packages/plugin-rdk/package.json b/packages/plugin-rdk/package.json index 867b743f..3099bb60 100644 --- a/packages/plugin-rdk/package.json +++ b/packages/plugin-rdk/package.json @@ -1,7 +1,7 @@ { "name": "@jspsych-contrib/plugin-rdk", "version": "1.1.0", - "description": "This plugin displays a Random Dot Kinematogram (RDK) and allows the subject to report the primary direction of motion by pressing a key on the keyboard.", + "description": "This plugin displays a Random Dot Kinematogram (RDK) and allows the participant to report the primary direction of motion by pressing a key on the keyboard.", "type": "module", "main": "dist/index.cjs", "exports": { @@ -37,11 +37,11 @@ }, "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-rdk", "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "^8.0.0" } } diff --git a/packages/plugin-rdk/readme.md b/packages/plugin-rdk/readme.md index 0cfbb7f3..42a7ab81 100644 --- a/packages/plugin-rdk/readme.md +++ b/packages/plugin-rdk/readme.md @@ -2,7 +2,7 @@ ## Overview -This plugin displays a Random Dot Kinematogram (RDK) and allows the subject to report the primary direction of motion by pressing a key on the keyboard. The stimulus can be displayed until a keyboard response is given or until a certain duration of time has passed. The RDK is fully customizable (see documentation below) and can display multiple apertures at the same time, each with its own parameters. +This plugin displays a Random Dot Kinematogram (RDK) and allows the participant to report the primary direction of motion by pressing a key on the keyboard. The stimulus can be displayed until a keyboard response is given or until a certain duration of time has passed. The RDK is fully customizable (see documentation below) and can display multiple apertures at the same time, each with its own parameters. ## Loading diff --git a/packages/plugin-rdk/src/index.ts b/packages/plugin-rdk/src/index.ts index 9652268f..a5a76874 100644 --- a/packages/plugin-rdk/src/index.ts +++ b/packages/plugin-rdk/src/index.ts @@ -2,8 +2,9 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; const info = { name: "rdk", + version: "2.0.0", parameters: { - /** Array containing the valid key(s) that the subject can press to indicate a response. */ + /** Array containing the valid key(s) that the participant can press to indicate a response. */ choices: { type: ParameterType.KEYS, pretty_name: "Choices", @@ -196,6 +197,177 @@ const info = { default: 1, }, }, + data: { + /** The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first + * began playing until the participant's response. Will be -1 if the trial has timed out + * without the participant pressing a valid key. + */ + rt: { + type: ParameterType.INT, + }, + /** The key that the participant pressed in response to the stimulus. */ + response: { + type: ParameterType.STRING, + }, + /** Indicates if the participant's response was correct or not. */ + correct: { + type: ParameterType.BOOL, + }, + /** Array containing the valid key(s) that the participant can press to indicate a response. */ + choices: { + type: ParameterType.STRING, + array: true, + }, + /** Array containing the correct key(s) that the participant could choose. */ + correct_choice: { + type: ParameterType.STRING, + array: true, + }, + /** The amount of time that the stimulus is displayed on the screen in ms. + * If -1, the stimulus will be displayed until the participant keys in a valid response. */ + trial_duration: { + type: ParameterType.INT, + }, + /** Whether a participant's response will end the trial or not. */ + response_ends_trial: { + type: ParameterType.BOOL, + }, + /** Number of apertures presented during the trial. */ + number_of_apertures: { + type: ParameterType.INT, + }, + /** Number of dots per set, equivalent to dots per frame. */ + number_of_dots: { + type: ParameterType.INT, + }, + /** Number of sets of dots to cycle through. */ + number_of_sets: { + type: ParameterType.INT, + }, + /** The direction of movement for coherent dots in degrees, from 0 degrees = 3 o'clock direction increasing counterclockwise. */ + coherent_direction: { + type: ParameterType.INT, + }, + /** Proportion of dots that move together. */ + coherence: { + type: ParameterType.FLOAT, + }, + /** Proportion of dots moving in the opposite direction as the coherent dots. */ + opposite_coherence: { + type: ParameterType.FLOAT, + }, + /** Radius of each dot in pixels if each dot is of 'circle' type. */ + dot_radius: { + type: ParameterType.INT, + }, + /** Length of each dot side in pixels if each dot is of 'square' type. */ + dot_side_length: { + type: ParameterType.INT, + }, + /** Number of frames a dot will keep following its trajectory before it is redrawn at a new location. */ + dot_life: { + type: ParameterType.INT, + }, + /** Number of pixel lengths a dot will move in each frame. */ + move_distance: { + type: ParameterType.INT, + }, + /** Width of aperture in pixels, along with height of the aperture if it is square, or diameter if it is circle. */ + aperture_width: { + type: ParameterType.INT, + }, + /** Height of the aperture in pixels. Ignored for square or circle apertures. */ + aperture_height: { + type: ParameterType.INT, + }, + /** The color of the dots. */ + dot_color: { + type: ParameterType.STRING, + }, + /** The shape of the dots. */ + dot_shape: { + type: ParameterType.STRING, + }, + /** The background color of the stimulus. */ + background_color: { + type: ParameterType.STRING, + }, + /** The Signal Selection Rule and Noise Type */ + RDK_type: { + type: ParameterType.INT, + }, + /** The shape of the aperture. (1 - Circle, 2 - Ellipse, 3 - Square, 4 - Rectangle) */ + aperture_type: { + type: ParameterType.INT, + }, + /** The type of reinsertion of a dot that has gone out of bounds. + * 1 - Randomly appear anywhere in the aperture. + * 2 - Appear on the opposite edge of the aperture. */ + reinsert_type: { + type: ParameterType.INT, + }, + /** The average frame rate for the trial, in ms. */ + frame_rate: { + type: ParameterType.FLOAT, + }, + /** The array of frame times in ms for the trial. */ + frame_rate_array: { + type: ParameterType.INT, + array: true, + }, + /** The number of frames in the trial. */ + number_of_frames: { + type: ParameterType.INT, + }, + /** The x-coordinate of the center of the aperture, in pixels. */ + aperture_center_x: { + type: ParameterType.INT, + }, + /** The y-coordinate of the center of the aperture, in pixels. */ + aperture_center_y: { + type: ParameterType.INT, + }, + /** If true, a fixation cross was displayed. */ + fixation_cross: { + type: ParameterType.BOOL, + }, + /** The width of the fixation cross in pixels. */ + fixation_cross_width: { + type: ParameterType.INT, + }, + /** The height of the fixation cross in pixels. */ + fixation_cross_height: { + type: ParameterType.INT, + }, + /** The color of the fixation cross. */ + fixation_cross_color: { + type: ParameterType.STRING, + }, + /** The thickness of the fixation cross, in pixels. */ + fixation_cross_thickness: { + type: ParameterType.INT, + }, + /** If true, a border was displayed around the aperture. */ + border: { + type: ParameterType.BOOL, + }, + /** The thickness of the border in pixels. */ + border_thickness: { + type: ParameterType.INT, + }, + /** The color of the border. */ + border_color: { + type: ParameterType.STRING, + }, + /** The width of the canvas in pixels. */ + canvas_width: { + type: ParameterType.INT, + }, + /** The height of the canvas in pixels. */ + canvas_height: { + type: ParameterType.INT, + }, + }, }; type Info = typeof info; @@ -515,7 +687,7 @@ class RdkPlugin implements JsPsychPlugin { //Variable to start the timer when the time comes var timerHasStarted = false; - //Initialize object to store the response data. Default values of -1 are used if the trial times out and the subject has not pressed a valid key + //Initialize object to store the response data. Default values of -1 are used if the trial times out and the participant has not pressed a valid key var response = { rt: -1, key: "", @@ -547,9 +719,9 @@ class RdkPlugin implements JsPsychPlugin { const startKeyboardListener = () => { //Start the response listener if there are choices for keys if (choices != "NO_KEYS") { - //Create the keyboard listener to listen for subjects' key response + //Create the keyboard listener to listen for participants' key response keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({ - callback_function: after_response, //Function to call once the subject presses a valid key + callback_function: after_response, //Function to call once the participant presses a valid key valid_responses: choices, //The keys that will be considered a valid response and cause the callback function to be called rt_method: "performance", //The type of method to record timing information. persist: false, //If set to false, keyboard listener will only trigger the first time a valid key is pressed. If set to true, it has to be explicitly cancelled by the cancelKeyboardResponse plugin API. @@ -575,7 +747,7 @@ class RdkPlugin implements JsPsychPlugin { frameRate = (frameRate as number[]).reduce((total, current) => total + current) / numberOfFrames; //Sum up all the elements in the array } else { - frameRate = 0; //Set to zero if the subject presses an answer before a frame is shown (i.e. if frameRate is an empty array) + frameRate = 0; //Set to zero if the participant presses an answer before a frame is shown (i.e. if frameRate is an empty array) } //Kill the keyboard listener if keyboardListener has been defined @@ -586,8 +758,8 @@ class RdkPlugin implements JsPsychPlugin { //Place all the data to be saved from this trial in one data object var trial_data = { rt: response.rt, //The response time - response: response.key, //The key that the subject pressed - correct: correctOrNot(), //If the subject response was correct + response: response.key, //The key that the participant pressed + correct: correctOrNot(), //If the participant response was correct choices: choices, //The set of valid keys correct_choice: correct_choice, //The correct choice(s) trial_duration: trial_duration, //The trial duration @@ -627,9 +799,6 @@ class RdkPlugin implements JsPsychPlugin { canvas_height: canvasHeight, }; - //Remove the canvas as the child of the display_element element - display_element.innerHTML = ""; - //Restore the settings to JsPsych defaults body.style.margin = originalMargin; body.style.padding = originalPadding; @@ -650,7 +819,7 @@ class RdkPlugin implements JsPsychPlugin { //----JsPsych Functions Begin---- - //Function to record the first response by the subject + //Function to record the first response by the participant function after_response(info) { //If the response has not been recorded, record it if (response.key == "") { @@ -1368,7 +1537,7 @@ class RdkPlugin implements JsPsychPlugin { //frameRequestID saves a long integer that is the ID of this frame request. The ID is then used to terminate the request below. var frameRequestID = window.requestAnimationFrame(animate); - //Start to listen to subject's key responses + //Start to listen to participant's key responses startKeyboardListener(); //Delare a timestamp @@ -1386,8 +1555,8 @@ class RdkPlugin implements JsPsychPlugin { //If the timer has not been started and it is set, then start the timer if (!timerHasStarted && trial_duration > 0) { //If the trial duration is set, then set a timer to count down and call the end_trial function when the time is up - //(If the subject did not press a valid keyboard response within the trial duration, then this will end the trial) - timeoutID = window.setTimeout(end_trial, trial_duration); //This timeoutID is then used to cancel the timeout should the subject press a valid key + //(If the participant did not press a valid keyboard response within the trial duration, then this will end the trial) + timeoutID = window.setTimeout(end_trial, trial_duration); //This timeoutID is then used to cancel the timeout should the participant press a valid key //The timer has started, so we set the variable to true so it does not start more timers timerHasStarted = true; } From a13c8fd75c6275627cc9509b1a96c14c84e27662 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:12:55 -0400 Subject: [PATCH 26/30] remove remaining timeout and display clears --- packages/plugin-copying-task/src/index.js | 6 ------ packages/plugin-corsi-blocks/src/index.ts | 1 - packages/plugin-gamepad/src/index.ts | 1 - packages/plugin-html-choice/src/index.ts | 7 ------- packages/plugin-html-keyboard-response-raf/src/index.ts | 3 --- packages/plugin-html-keyboard-slider/src/index.ts | 1 - packages/plugin-html-multi-response/src/index.ts | 3 --- packages/plugin-html-swipe-response/src/index.ts | 3 --- packages/plugin-html-vas-response/index.js | 4 ---- packages/plugin-image-array-keyboard-response/src/index.ts | 6 ------ packages/plugin-image-multi-response/src/index.ts | 3 --- packages/plugin-image-swipe-response/src/index.ts | 6 ------ packages/plugin-ios/index.js | 2 +- packages/plugin-libet-intentional-binding/index.js | 3 +-- packages/plugin-rok/src/index.ts | 3 --- packages/plugin-self-paced-reading/src/index.ts | 3 +-- packages/plugin-survey-number/src/index.ts | 2 +- packages/plugin-survey-slider/src/index.ts | 2 -- packages/plugin-vsl-grid-scene/src/index.ts | 2 -- 19 files changed, 4 insertions(+), 57 deletions(-) diff --git a/packages/plugin-copying-task/src/index.js b/packages/plugin-copying-task/src/index.js index 90c92d9d..74af4696 100644 --- a/packages/plugin-copying-task/src/index.js +++ b/packages/plugin-copying-task/src/index.js @@ -926,9 +926,6 @@ var jsPsychCopyingTask = (function (jspsych) { var endTime = Math.round(performance.now()); var response_time = endTime - startTime; - // kill any remaining setTimeout handlers - this.jsPsych.pluginAPI.clearAllTimeouts(); - // clearInterval(interval_ID) var trial_completed = checkIfDone(); @@ -946,9 +943,6 @@ var jsPsychCopyingTask = (function (jspsych) { canvas_offset_top_left: [canvas_rect.top, canvas_rect.left], }; - // clear the display - display_element.innerHTML = ""; - // move on to the next trial this.jsPsych.finishTrial(trial_data); }; diff --git a/packages/plugin-corsi-blocks/src/index.ts b/packages/plugin-corsi-blocks/src/index.ts index 36983a0f..25cce656 100644 --- a/packages/plugin-corsi-blocks/src/index.ts +++ b/packages/plugin-corsi-blocks/src/index.ts @@ -237,7 +237,6 @@ class CorsiBlocksPlugin implements JsPsychPlugin { }; const end_trial = () => { - display_element.innerHTML = ""; this.jsPsych.finishTrial(trial_data); }; diff --git a/packages/plugin-gamepad/src/index.ts b/packages/plugin-gamepad/src/index.ts index 79a1395f..03abc55a 100644 --- a/packages/plugin-gamepad/src/index.ts +++ b/packages/plugin-gamepad/src/index.ts @@ -214,7 +214,6 @@ class GamepadPlugin implements JsPsychPlugin { let finish_trial: Function = (data: object) => { window.cancelAnimationFrame(this.animation_frame_id); - display_element.innerHTML = ""; this.minature_gamepad_wrapper.remove(); this.jsPsych.finishTrial(data); }; diff --git a/packages/plugin-html-choice/src/index.ts b/packages/plugin-html-choice/src/index.ts index e3b240dc..5c809086 100644 --- a/packages/plugin-html-choice/src/index.ts +++ b/packages/plugin-html-choice/src/index.ts @@ -125,9 +125,6 @@ class HtmlChoicePlugin implements JsPsychPlugin { // function to end trial when it is time const end_trial = () => { - // kill any remaining setTimeout handlers - this.jsPsych.pluginAPI.clearAllTimeouts(); - // gather the data to store for the trial var trial_data = { rt: response.rt, @@ -136,9 +133,6 @@ class HtmlChoicePlugin implements JsPsychPlugin { value: response.value, }; - // clear the display - display_element.innerHTML = ""; - // move on to the next trial this.jsPsych.finishTrial(trial_data); }; @@ -165,7 +159,6 @@ class HtmlChoicePlugin implements JsPsychPlugin { } if (trial.response_ends_trial) { - this.jsPsych.pluginAPI.clearAllTimeouts(); this.jsPsych.pluginAPI.setTimeout(end_trial, trial.time_after_response); } }; diff --git a/packages/plugin-html-keyboard-response-raf/src/index.ts b/packages/plugin-html-keyboard-response-raf/src/index.ts index b2cb6602..7c428e27 100644 --- a/packages/plugin-html-keyboard-response-raf/src/index.ts +++ b/packages/plugin-html-keyboard-response-raf/src/index.ts @@ -173,9 +173,6 @@ class HtmlKeyboardResponseRafPlugin implements JsPsychPlugin { response: response.key, }; - // clear the display - display_element.innerHTML = ""; - // move on to the next trial this.jsPsych.finishTrial(trial_data); }; diff --git a/packages/plugin-html-keyboard-slider/src/index.ts b/packages/plugin-html-keyboard-slider/src/index.ts index ccc36246..c4423bbe 100644 --- a/packages/plugin-html-keyboard-slider/src/index.ts +++ b/packages/plugin-html-keyboard-slider/src/index.ts @@ -559,7 +559,6 @@ class HtmlKeyboardSliderPlugin implements JsPsychPlugin { //clear and cancel things clearKeybuffer(); this.jsPsych.pluginAPI.cancelKeyboardResponse(this.keyboardListener); - display_element.innerHTML = ""; // if no response and trial_duration not set if (data.response === null && trial.trial_duration === null) diff --git a/packages/plugin-html-multi-response/src/index.ts b/packages/plugin-html-multi-response/src/index.ts index 1048aff6..6557cf52 100644 --- a/packages/plugin-html-multi-response/src/index.ts +++ b/packages/plugin-html-multi-response/src/index.ts @@ -206,9 +206,6 @@ class HtmlMultiResponsePlugin implements JsPsychPlugin { // function to end trial when it is time const end_trial = () => { - // kill any remaining setTimeout handlers - this.jsPsych.pluginAPI.clearAllTimeouts(); - // kill keyboard listeners if (typeof keyboardListener !== "undefined") { this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener); diff --git a/packages/plugin-html-swipe-response/src/index.ts b/packages/plugin-html-swipe-response/src/index.ts index 665be418..2b2dfa8a 100644 --- a/packages/plugin-html-swipe-response/src/index.ts +++ b/packages/plugin-html-swipe-response/src/index.ts @@ -414,9 +414,6 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { // function to end trial when it is time const end_trial = () => { - // kill any remaining setTimeout handlers - this.jsPsych.pluginAPI.clearAllTimeouts(); - // kill keyboard listeners if (typeof keyboardListener !== "undefined") { this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener); diff --git a/packages/plugin-html-vas-response/index.js b/packages/plugin-html-vas-response/index.js index 672c57b1..5678ccc8 100644 --- a/packages/plugin-html-vas-response/index.js +++ b/packages/plugin-html-vas-response/index.js @@ -281,8 +281,6 @@ var jsPsychHtmlVasResponse = (function (jspsych) { }; function end_trial() { - jsPsych.pluginAPI.clearAllTimeouts(); - // save data var trialdata = { rt: response.rt, @@ -291,8 +289,6 @@ var jsPsychHtmlVasResponse = (function (jspsych) { clicks: clicks, }; - display_element.innerHTML = ""; - // next trial jsPsych.finishTrial(trialdata); } diff --git a/packages/plugin-image-array-keyboard-response/src/index.ts b/packages/plugin-image-array-keyboard-response/src/index.ts index bd3b5b44..f1ad016c 100644 --- a/packages/plugin-image-array-keyboard-response/src/index.ts +++ b/packages/plugin-image-array-keyboard-response/src/index.ts @@ -216,9 +216,6 @@ class ImageArrayKeyboardResponsePlugin implements JsPsychPlugin { // function to end trial when it is time const end_trial = () => { - // kill any remaining setTimeout handlers - this.jsPsych.pluginAPI.clearAllTimeouts(); - // kill keyboard listeners if (typeof keyboardListener !== "undefined") { this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener); @@ -231,9 +228,6 @@ class ImageArrayKeyboardResponsePlugin implements JsPsychPlugin { response: response.key, }; - // clear the display - display_element.innerHTML = ""; - // move on to the next trial this.jsPsych.finishTrial(trial_data); }; diff --git a/packages/plugin-image-multi-response/src/index.ts b/packages/plugin-image-multi-response/src/index.ts index 974c3d48..f3f08169 100644 --- a/packages/plugin-image-multi-response/src/index.ts +++ b/packages/plugin-image-multi-response/src/index.ts @@ -346,9 +346,6 @@ class ImageMultiResponsePlugin implements JsPsychPlugin { // function to end trial when it is time const end_trial = () => { - // kill any remaining setTimeout handlers - this.jsPsych.pluginAPI.clearAllTimeouts(); - // kill keyboard listeners if (typeof keyboardListener !== "undefined") { this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener); diff --git a/packages/plugin-image-swipe-response/src/index.ts b/packages/plugin-image-swipe-response/src/index.ts index 3568d829..567f1c4f 100644 --- a/packages/plugin-image-swipe-response/src/index.ts +++ b/packages/plugin-image-swipe-response/src/index.ts @@ -394,9 +394,6 @@ class ImageSwipeResponsePlugin implements JsPsychPlugin { // function to end trial when it is time const end_trial = () => { - // kill any remaining setTimeout handlers - this.jsPsych.pluginAPI.clearAllTimeouts(); - // kill keyboard listeners if (typeof keyboardListener !== "undefined") { this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener); @@ -413,9 +410,6 @@ class ImageSwipeResponsePlugin implements JsPsychPlugin { response_source: response.source, }; - // clear the display - display_element.innerHTML = ""; - // move on to the next trial this.jsPsych.finishTrial(trial_data); }; diff --git a/packages/plugin-ios/index.js b/packages/plugin-ios/index.js index 51a8dbc4..9127cda6 100644 --- a/packages/plugin-ios/index.js +++ b/packages/plugin-ios/index.js @@ -434,7 +434,7 @@ var jsPsychIos = (function (jspsych) { prompt: trial.prompt, response: response.response, }; - display_element.innerHTML = ""; + // next trial jsPsych.finishTrial(trialdata); } diff --git a/packages/plugin-libet-intentional-binding/index.js b/packages/plugin-libet-intentional-binding/index.js index 913a6ff9..0c9559d8 100644 --- a/packages/plugin-libet-intentional-binding/index.js +++ b/packages/plugin-libet-intentional-binding/index.js @@ -569,8 +569,7 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { callback_function: function (info) { // trial_data.rt = info.rt; // trial_data.keypress_ms = performance.now(); - // cancel end of trial timeout - jsPsych.pluginAPI.clearAllTimeouts(); + // compute clock theta at the time of response trial_data.theta.keypress = clock.theta; if (info.rt < trial.early_ms) { diff --git a/packages/plugin-rok/src/index.ts b/packages/plugin-rok/src/index.ts index 92efe747..47536a0a 100644 --- a/packages/plugin-rok/src/index.ts +++ b/packages/plugin-rok/src/index.ts @@ -1065,9 +1065,6 @@ class RokPlugin implements JsPsychPlugin { aperture_mode: aperture_mode, }; - //Clear the body - display_element.innerHTML = ""; - //Restore the settings to JsPsych defaults body.style.margin = originalMargin; body.style.padding = originalPadding; diff --git a/packages/plugin-self-paced-reading/src/index.ts b/packages/plugin-self-paced-reading/src/index.ts index 53f7034e..2ab1ac3e 100644 --- a/packages/plugin-self-paced-reading/src/index.ts +++ b/packages/plugin-self-paced-reading/src/index.ts @@ -338,8 +338,7 @@ class SelfPacedReadingPlugin implements JsPsychPlugin { ctx.fillRect(canvas_rect[0], canvas_rect[1], canvas_rect[2], canvas_rect[3]); } - // kill any remaining setTimeout handlers + kill keyboard listeners - this.jsPsych.pluginAPI.clearAllTimeouts(); + // kill any remaining keyboard listeners this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener); // move on to the next trial diff --git a/packages/plugin-survey-number/src/index.ts b/packages/plugin-survey-number/src/index.ts index c9556d36..2bd4a2ad 100644 --- a/packages/plugin-survey-number/src/index.ts +++ b/packages/plugin-survey-number/src/index.ts @@ -224,7 +224,7 @@ class SurveyNumberPlugin implements JsPsychPlugin { rt: response_time, response: question_data, }; - display_element.innerHTML = ""; + // next trial this.jsPsych.finishTrial(trialdata); }); diff --git a/packages/plugin-survey-slider/src/index.ts b/packages/plugin-survey-slider/src/index.ts index 89421803..9836a202 100644 --- a/packages/plugin-survey-slider/src/index.ts +++ b/packages/plugin-survey-slider/src/index.ts @@ -381,8 +381,6 @@ class SurveySliderPlugin implements JsPsychPlugin { question_order: JSON.stringify(question_order), }; - display_element.innerHTML = ""; - // next trial this.jsPsych.finishTrial(trial_data); }); diff --git a/packages/plugin-vsl-grid-scene/src/index.ts b/packages/plugin-vsl-grid-scene/src/index.ts index 91bf6ab0..73718bd3 100644 --- a/packages/plugin-vsl-grid-scene/src/index.ts +++ b/packages/plugin-vsl-grid-scene/src/index.ts @@ -63,8 +63,6 @@ class VslGridScenePlugin implements JsPsychPlugin { }, trial.trial_duration); const endTrial = () => { - display_element.innerHTML = ""; - var trial_data = { stimulus: trial.stimuli, }; From 132c1f59b3a3ee143a8bc807cef27c9ccc66f761 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Fri, 18 Oct 2024 23:49:43 -0400 Subject: [PATCH 27/30] fix and complete documentation for all plugins --- README.md | 4 +- .../docs/jspsych-device-motion.md | 2 +- .../extension-mediapipe-face-mesh/README.md | 2 +- .../docs/jspsych-touchscreen-buttons.md | 2 +- .../extension-touchscreen-buttons/readme.md | 2 +- .../plugin-audio-multi-response/README.md | 6 +-- .../docs/jspsych-audio-multi-response.md | 4 +- .../plugin-audio-multi-response/src/index.ts | 2 +- .../plugin-audio-swipe-response/README.md | 2 +- .../docs/jspsych-audio-swipe-response.md | 4 +- .../docs/jspsych-copying-task.md | 7 ++-- packages/plugin-corsi-blocks/README.md | 2 +- .../docs/jspsych-corsi-blocks.md | 14 +++---- packages/plugin-corsi-blocks/src/index.ts | 4 +- packages/plugin-gamepad/README.md | 6 +-- .../plugin-gamepad/docs/jspsych-gamepad.md | 4 +- .../docs/jspsych-html-choice.md | 15 +++---- packages/plugin-html-choice/src/index.ts | 4 +- .../README.md | 2 +- .../docs/html-keyboard-response-raf.md | 6 +-- .../src/index.ts | 6 +-- .../plugin-html-keyboard-slider/README.md | 2 +- .../docs/html-keyboard-slider.md | 4 +- .../plugin-html-keyboard-slider/src/index.ts | 5 +-- packages/plugin-html-multi-response/README.md | 4 +- .../docs/jspsych-html-multi-response.md | 20 +++++----- .../plugin-html-multi-response/src/index.ts | 14 +++---- packages/plugin-html-swipe-response/README.md | 4 +- .../docs/jspsych-html-swipe-response.md | 26 ++++++------- .../plugin-html-swipe-response/src/index.ts | 24 ++++++------ packages/plugin-html-vas-response/README.md | 2 +- .../docs/jspsych-html-vas-response.md | 4 +- .../jspsych-image-array-keyboard-response.md | 16 ++++---- .../readme.md | 4 +- .../src/index.ts | 8 ++-- .../plugin-image-multi-response/README.md | 4 +- .../docs/jspsych-image-multi-response.md | 20 +++++----- .../plugin-image-multi-response/src/index.ts | 14 +++---- .../plugin-image-swipe-response/README.md | 4 +- .../docs/jspsych-image-swipe-response.md | 24 ++++++------ .../plugin-image-swipe-response/src/index.ts | 14 +++---- packages/plugin-ios/README.md | 2 +- packages/plugin-ios/docs/jspsych-ios.md | 29 +++++++------- packages/plugin-ios/index.js | 27 ++++++++++++- .../README.md | 2 +- .../docs/jspsych-libet-intentional-binding.md | 7 ++-- .../plugin-libet-intentional-binding/index.js | 2 +- packages/plugin-nextcloud-filedrop/README.md | 39 +++++++++++-------- packages/plugin-pipe/docs/jspsych-pipe.md | 18 ++++----- .../jspsych-plugin-pipe-example-1.html | 6 +-- .../jspsych-plugin-pipe-example-3.html | 6 +-- packages/plugin-pipe/readme.md | 4 +- packages/plugin-rdk/docs/jspsych-rdk.md | 4 +- packages/plugin-rdk/readme.md | 3 +- packages/plugin-rok/docs/jspsych-rok.md | 7 ++-- packages/plugin-rok/readme.md | 2 +- packages/plugin-rok/src/index.ts | 20 +++++----- .../docs/jspsych-self-paced-reading.md | 4 +- .../plugin-self-paced-reading/src/index.ts | 2 +- packages/plugin-survey-number/README.md | 2 +- .../docs/survey-number.md | 18 +++++++-- packages/plugin-survey-slider/README.md | 2 +- .../docs/survey-slider.md | 16 ++++++-- packages/plugin-survey-slider/src/index.ts | 1 + .../README.md | 2 +- ...spsych-video-several-keyboard-responses.md | 13 ++++--- .../src/index.ts | 10 ++--- .../docs/jspsych-vsl-animate-occlusion.md | 4 +- .../plugin-vsl-animate-occlusion/readme.md | 2 +- .../plugin-vsl-animate-occlusion/src/index.ts | 2 +- .../docs/jspsych-vsl-grid-scene.md | 4 +- packages/plugin-vsl-grid-scene/readme.md | 2 +- .../plugin-template-js/docs/docs-template.md | 4 +- .../plugin-template-ts/docs/docs-template.md | 4 +- 74 files changed, 320 insertions(+), 267 deletions(-) diff --git a/README.md b/README.md index daf12359..0f5e5e08 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,8 @@ The `/packages` directory also contains four template sub-folders that can be us [libet-intentional-binding](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-libet-intentional-binding/README.md) | [Isaac Kinley](https://github.com/kinleyid) | This plugin measures intentional binding using a Libet clock, and allows the participant to estimate the timing of events by adjusting the clock hand themselves. [nextcloud-filedrop](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-nextcloud-filedrop/README.md) | [C. Martin Grewe](https://github.com/mgrewe) | This plugin provides permanent storage of data collected during an experiment using a nextcloud instance. [pipe](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-pipe/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | jsPsych plugin to faciliate communication with [DataPipe](https://pipe.jspsych.org) -[rdk](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-rdk/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a Random Dot Kinematogram (RDK) and allows the subject to report the primary direction of motion by pressing a key on the keyboard. -[rok](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-rok/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays a Random Object Kinematogram (ROK) and allows the subject to report the primary direction of motion or the primary orientation by pressing a key on the keyboard. +[rdk](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-rdk/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a Random Dot Kinematogram (RDK) and allows the participant to report the primary direction of motion by pressing a key on the keyboard. +[rok](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-rok/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays a Random Object Kinematogram (ROK) and allows the participant to report the primary direction of motion or the primary orientation by pressing a key on the keyboard. [self-paced-reading](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-self-paced-reading/README.md) | [igmmgi](https://github.com/igmmgi) | Self-paced reading tasks with different display options. [survey-number](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-survey-number/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a survey question and collects a numeric response. [survey-slider](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-survey-slider/README.md) | [Dominique Makowski](https://github.com/DominiqueMakowski) | Add several analogue scales on the same page for use in questionnaires. diff --git a/packages/extension-device-motion/docs/jspsych-device-motion.md b/packages/extension-device-motion/docs/jspsych-device-motion.md index d76ae481..f4ef9c4f 100644 --- a/packages/extension-device-motion/docs/jspsych-device-motion.md +++ b/packages/extension-device-motion/docs/jspsych-device-motion.md @@ -2,7 +2,7 @@ ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ----------- | ---------------------------------------- | diff --git a/packages/extension-mediapipe-face-mesh/README.md b/packages/extension-mediapipe-face-mesh/README.md index 26a08e8a..f31a4bf4 100644 --- a/packages/extension-mediapipe-face-mesh/README.md +++ b/packages/extension-mediapipe-face-mesh/README.md @@ -66,7 +66,7 @@ record | boolean | false | Should the data generated as described below recorded ### Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. | Name | Type | Value | | ---------------- | ----------- | ---------------------------------------- | diff --git a/packages/extension-touchscreen-buttons/docs/jspsych-touchscreen-buttons.md b/packages/extension-touchscreen-buttons/docs/jspsych-touchscreen-buttons.md index 046b5a73..ac82382b 100644 --- a/packages/extension-touchscreen-buttons/docs/jspsych-touchscreen-buttons.md +++ b/packages/extension-touchscreen-buttons/docs/jspsych-touchscreen-buttons.md @@ -1,6 +1,6 @@ # touchscreen-buttons extension -This extension displays touch buttons allows the subject to respond to stimuli via touchscreen on mobile devices. The +This extension displays touch buttons allows the participant to respond to stimuli via touchscreen on mobile devices. The touch button send key press events so that all jsPsych plugins that use keyboard input are compatible. ## Citation diff --git a/packages/extension-touchscreen-buttons/readme.md b/packages/extension-touchscreen-buttons/readme.md index e152ae1c..0d770637 100644 --- a/packages/extension-touchscreen-buttons/readme.md +++ b/packages/extension-touchscreen-buttons/readme.md @@ -2,7 +2,7 @@ ## Overview -This extension displays touch buttons that allow the subject to respond to stimuli via a touchscreen on mobile devices. The touch button sends key press events so that all jsPsych plugins that use keyboard input are compatible. +This extension displays touch buttons that allow the participant to respond to stimuli via a touchscreen on mobile devices. The touch button sends key press events so that all jsPsych plugins that use keyboard input are compatible. ## Loading diff --git a/packages/plugin-audio-multi-response/README.md b/packages/plugin-audio-multi-response/README.md index 0215fdc9..a55cfaf9 100644 --- a/packages/plugin-audio-multi-response/README.md +++ b/packages/plugin-audio-multi-response/README.md @@ -2,13 +2,13 @@ ## Overview -This plugin plays an audio file and records responses generated by both button click and the keyboard. Allowing multiple response modalities is useful when designing assessments that will be administered on both desktop and mobile (e.g., phone or tablet) devices. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin plays an audio file and records responses generated by both button click and the keyboard. Allowing multiple response modalities is useful when designing assessments that will be administered on both desktop and mobile (e.g., phone or tablet) devices. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. If the browser supports it, audio files are played using the WebAudio API. This allows for reasonably precise timing of the playback. The timing of responses generated is measured against the WebAudio specific clock, improving the measurement of response times. If the browser does not support the WebAudio API, then the audio file is played with HTML5 audio. Audio files can be automatically preloaded by jsPsych using the preload plugin. However, if you are using timeline variables or another dynamic method to specify the audio stimulus, then you will need to manually preload the audio. -The trial can end when the subject responds, when the audio file has finished playing, or if the subject has failed to respond within a fixed length of time. You can also prevent a response from being recorded before the audio has finished playing. +The trial can end when the participant responds, when the audio file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a response from being recorded before the audio has finished playing. ## Loading @@ -18,7 +18,7 @@ The trial can end when the subject responds, when the audio file has finished pl ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-audio-multi-response/docs/jspsych-audio-multi-response.md b/packages/plugin-audio-multi-response/docs/jspsych-audio-multi-response.md index d5e69295..5cd987ac 100644 --- a/packages/plugin-audio-multi-response/docs/jspsych-audio-multi-response.md +++ b/packages/plugin-audio-multi-response/docs/jspsych-audio-multi-response.md @@ -10,7 +10,7 @@ The trial can end when the participant responds, when the audio file has finishe ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ----------|------|---------------|------------ | @@ -29,7 +29,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | diff --git a/packages/plugin-audio-multi-response/src/index.ts b/packages/plugin-audio-multi-response/src/index.ts index 46e08db1..524f24b9 100644 --- a/packages/plugin-audio-multi-response/src/index.ts +++ b/packages/plugin-audio-multi-response/src/index.ts @@ -18,7 +18,7 @@ const info = { default: [], array: true, }, - /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */ + /** Array containing the key(s) the participant is allowed to press to respond to the stimulus. */ keyboard_choices: { type: ParameterType.KEYS, pretty_name: "Keyboard Choices", diff --git a/packages/plugin-audio-swipe-response/README.md b/packages/plugin-audio-swipe-response/README.md index 360d0831..9b473921 100644 --- a/packages/plugin-audio-swipe-response/README.md +++ b/packages/plugin-audio-swipe-response/README.md @@ -18,7 +18,7 @@ The trial can end when the participant responds, when the audio file has finishe ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-audio-swipe-response/docs/jspsych-audio-swipe-response.md b/packages/plugin-audio-swipe-response/docs/jspsych-audio-swipe-response.md index 3b71b2ad..b8162128 100644 --- a/packages/plugin-audio-swipe-response/docs/jspsych-audio-swipe-response.md +++ b/packages/plugin-audio-swipe-response/docs/jspsych-audio-swipe-response.md @@ -10,7 +10,7 @@ The trial can end when the participant responds, when the audio file has finishe ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ----------|------|---------------|------------ | @@ -28,7 +28,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | diff --git a/packages/plugin-copying-task/docs/jspsych-copying-task.md b/packages/plugin-copying-task/docs/jspsych-copying-task.md index 161f9247..68a09a86 100644 --- a/packages/plugin-copying-task/docs/jspsych-copying-task.md +++ b/packages/plugin-copying-task/docs/jspsych-copying-task.md @@ -1,11 +1,10 @@ # jspsych-copying-task plugin -This plugin runs a copying task. In a trial, an example grid (the "model", containing various stimuli) on the left must replicated in the middle grid (the "workspace"). To do this stimuli from the right grid (the "resources") can be picked up and dragged to the middle grid. You can use imgage files (e.g., .jpg/.png/.gif) as stimuli, or built in 'nonsense' shape stimuli in any color. The plugin records the actions of the participant what items are picked up and where they are placed. +This plugin runs a copying task. In a trial, an example grid (the "model", containing various stimuli) on the left must replicated in the middle grid (the "workspace"). To do this stimuli from the right grid (the "resources") can be picked up and dragged to the middle grid. You can use image files (e.g., .jpg/.png/.gif) as stimuli, or built in 'nonsense' shape stimuli in any color. The plugin records the actions of the participant what items are picked up and where they are placed. ## Parameters -Parameters can be left unspecified if the default value is acceptable. If more then one aperture is displayed most of the parameters should be specified as array (specified by the array column). -The elements of the array then apply to the corresponding aperture. Features that are not fully implemented yet are marked with an x +Parameters can be left unspecified if the default value is acceptable. If more then one aperture is displayed most of the parameters should be specified as array (specified by the array column). The elements of the array then apply to the corresponding aperture. So in addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. |Parameter|Type|Default Value| Descripton| |---------|----|-------------|-----------| @@ -29,7 +28,7 @@ The elements of the array then apply to the corresponding aperture. Features tha ## Data Generated -In addition to the default data collected by all plugins, this plugin collects all parameter data described above and the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. |Name|Type|Description| |----|----|-----------| diff --git a/packages/plugin-corsi-blocks/README.md b/packages/plugin-corsi-blocks/README.md index 0623de54..528f4efa 100644 --- a/packages/plugin-corsi-blocks/README.md +++ b/packages/plugin-corsi-blocks/README.md @@ -24,7 +24,7 @@ import jsPsychCorsiBlocks from '@jspsych-contrib/plugin-corsi-blocks'; ## Compatibility -jsPsych 7.3.2. +jsPsych v8.0. For compatibility with jsPsych v7.3.2, use version 1.0.0 of this plugin. (Earlier versions of jsPsych version 7 will work if you explicitly set the `blocks` parameter in a trial. Using the default `blocks` parameter requires `7.3.2` or later.) diff --git a/packages/plugin-corsi-blocks/docs/jspsych-corsi-blocks.md b/packages/plugin-corsi-blocks/docs/jspsych-corsi-blocks.md index 7fb729bd..da47a259 100644 --- a/packages/plugin-corsi-blocks/docs/jspsych-corsi-blocks.md +++ b/packages/plugin-corsi-blocks/docs/jspsych-corsi-blocks.md @@ -1,10 +1,10 @@ # jspsych-corsi-blocks plugin -This plugin displays a sequence of blocks and then gets the subject's response. The sequence can be displayed in either 'display' mode or 'input' mode. In 'display' mode, the sequence is displayed and the trial ends after the sequence is complete. In 'input' mode, the subject must click on the blocks in the correct order. +This plugin displays a sequence of blocks and then gets the participant's response. The sequence can be displayed in either 'display' mode or 'input' mode. In 'display' mode, the sequence is displayed and the trial ends after the sequence is complete. In 'input' mode, the participant must click on the blocks in the correct order. ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ----------|------|---------------|------------ | @@ -26,19 +26,19 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | | sequence | array | The sequence of block indexes that was displayed. | -| response | array | The sequence of block indexes that was selected by the subject. | -| correct | boolean | Whether the subject's response was correct. | -| rt | array | The time, in milliseconds, that the subject took to respond to each block. These times are cumulative, measured from the onset of the display. | +| response | array | The sequence of block indexes that was selected by the participant. | +| correct | boolean | Whether the participant's response was correct. | +| rt | array | The time, in milliseconds, that the participant took to respond to each block. These times are cumulative, measured from the onset of the display. | | blocks | array | The coordinates of the blocks that were displayed. | ## Examples -### Displaying a two-item sequence and then getting the subject's response. +### Displaying a two-item sequence and then getting the participant's response. ```javascript const show_sequence = { diff --git a/packages/plugin-corsi-blocks/src/index.ts b/packages/plugin-corsi-blocks/src/index.ts index 25cce656..3af05070 100644 --- a/packages/plugin-corsi-blocks/src/index.ts +++ b/packages/plugin-corsi-blocks/src/index.ts @@ -172,10 +172,10 @@ type Info = typeof info; * **corsi-blocks** * * This plugin displays a sequence of blocks and then gets the - * subject's response. The sequence can be displayed in either + * participant's response. The sequence can be displayed in either * 'display' mode or 'input' mode. In 'display' mode, the * sequence is displayed and the trial ends after the sequence - * is complete. In 'input' mode, the subject must click on the + * is complete. In 'input' mode, the participant must click on the * blocks in the correct order. * * @author Josh de Leeuw diff --git a/packages/plugin-gamepad/README.md b/packages/plugin-gamepad/README.md index 9b182a78..525666b1 100644 --- a/packages/plugin-gamepad/README.md +++ b/packages/plugin-gamepad/README.md @@ -6,11 +6,11 @@ This is a plugin that allows one to use gamepads in a jsPsych experiment. Curren ## Compatibility -jsPsych >= 7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.1 of this plugin. ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | --------- | ---- | ------------- | ----------- | @@ -23,7 +23,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | diff --git a/packages/plugin-gamepad/docs/jspsych-gamepad.md b/packages/plugin-gamepad/docs/jspsych-gamepad.md index b1aaaaeb..43e41908 100644 --- a/packages/plugin-gamepad/docs/jspsych-gamepad.md +++ b/packages/plugin-gamepad/docs/jspsych-gamepad.md @@ -10,7 +10,7 @@ jsPsych >= 7.0 ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | --------- | ---- | ------------- | ----------- | @@ -23,7 +23,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | diff --git a/packages/plugin-html-choice/docs/jspsych-html-choice.md b/packages/plugin-html-choice/docs/jspsych-html-choice.md index c19f135f..5c374260 100644 --- a/packages/plugin-html-choice/docs/jspsych-html-choice.md +++ b/packages/plugin-html-choice/docs/jspsych-html-choice.md @@ -5,14 +5,14 @@ This plugin displays clickable html elements that can be used to present a choic ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | |---------------------|-----------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | html_array | array of HTML-strings | *undefined* | The HTML elements to be displayed | | stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. | -| trial_duration | numeric | null | How long to wait for the subject to make a response before ending the trial in milliseconds. If the subject fails to make a response before this timer is reached, the subject's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | -| response_ends_trial | boolean | true | If true, then the trial will end whenever the subject makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the subject to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | +| trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | +| response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | | stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. | | values | array | null | Can be used to assign attributes to the html elements (for example, to use in a feedback animation) | | time_after_response | numeric | null | If respondes_ends_trial is set to true, this is the time the stimulus remains visible after the response (can be used for feedback animation) | @@ -20,13 +20,14 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | |----------|-----------------------|-----------------------------------------------------------| -| stimulus | array of HTML-strings | The array of HTML elements that were displayed | -| choice | numeric | The index of the chosen HTML element. | -| value | object | If given, the value attributed to the chosen HTML element | +| rt | numeric | The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant makes a response. | +| stimulus | array of HTML-strings | The array of HTML elements that were displayed. | +| choice | numeric | The index of the chosen HTML element. | +| value | object | If given, the value attributed to the chosen HTML element. | ## Example diff --git a/packages/plugin-html-choice/src/index.ts b/packages/plugin-html-choice/src/index.ts index 5c809086..fae258b3 100644 --- a/packages/plugin-html-choice/src/index.ts +++ b/packages/plugin-html-choice/src/index.ts @@ -23,7 +23,7 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** If true, trial will end when subject makes a response. */ + /** If true, trial will end when participant makes a response. */ response_ends_trial: { type: ParameterType.BOOL, pretty_name: "Response ends trial", @@ -137,7 +137,7 @@ class HtmlChoicePlugin implements JsPsychPlugin { this.jsPsych.finishTrial(trial_data); }; - // function to handle responses by the subject + // function to handle responses by the participant const after_response = (choice, value) => { // measure rt var end_time = performance.now(); diff --git a/packages/plugin-html-keyboard-response-raf/README.md b/packages/plugin-html-keyboard-response-raf/README.md index 8f3faa15..35ebf3e2 100644 --- a/packages/plugin-html-keyboard-response-raf/README.md +++ b/packages/plugin-html-keyboard-response-raf/README.md @@ -24,7 +24,7 @@ import jsPsychHtmlKeyboardResponseRaf from '@jspsych-contrib/plugin-html-keyboar ## Compatibility -jsPsych 7.0.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.1 of this plugin. ## Documentation diff --git a/packages/plugin-html-keyboard-response-raf/docs/html-keyboard-response-raf.md b/packages/plugin-html-keyboard-response-raf/docs/html-keyboard-response-raf.md index 7d25a6bb..08fb1dd6 100644 --- a/packages/plugin-html-keyboard-response-raf/docs/html-keyboard-response-raf.md +++ b/packages/plugin-html-keyboard-response-raf/docs/html-keyboard-response-raf.md @@ -1,10 +1,10 @@ # html-keyboard-response-raf -This plugin implements the same functionality as the html-keyboard-response plugin, but uses requestAnimationFrame internally for timing +This plugin implements the same functionality as the html-keyboard-response plugin, but uses requestAnimationFrame internally for timing. ## Parameters -In addition to the [parameters available in all plugins](https://jspsych.org/latest/overview/plugins.md#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ------------------- | ---------------- | ------------------ | ---------------------------------------- | @@ -16,7 +16,7 @@ In addition to the [parameters available in all plugins](https://jspsych.org/lat | response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | ## Data Generated -In addition to the [default data collected by all plugins](https://jspsych.org/latest/overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | diff --git a/packages/plugin-html-keyboard-response-raf/src/index.ts b/packages/plugin-html-keyboard-response-raf/src/index.ts index 7c428e27..f185d67b 100644 --- a/packages/plugin-html-keyboard-response-raf/src/index.ts +++ b/packages/plugin-html-keyboard-response-raf/src/index.ts @@ -13,7 +13,7 @@ const info = { default: undefined, }, /** - * Array containing the key(s) the subject is allowed to press to respond to the stimulus. + * Array containing the key(s) the participant is allowed to press to respond to the stimulus. */ choices: { type: ParameterType.KEYS, @@ -45,7 +45,7 @@ const info = { default: null, }, /** - * If true, trial will end when subject makes a response. + * If true, trial will end when participant makes a response. */ response_ends_trial: { type: ParameterType.BOOL, @@ -177,7 +177,7 @@ class HtmlKeyboardResponseRafPlugin implements JsPsychPlugin { this.jsPsych.finishTrial(trial_data); }; - // function to handle responses by the subject + // function to handle responses by the participant const after_response = (info) => { // after a valid response, the stimulus will have the CSS class 'responded' // which can be used to provide visual feedback that a response was recorded diff --git a/packages/plugin-html-keyboard-slider/README.md b/packages/plugin-html-keyboard-slider/README.md index 88eb0aa6..1a1d70b7 100644 --- a/packages/plugin-html-keyboard-slider/README.md +++ b/packages/plugin-html-keyboard-slider/README.md @@ -24,7 +24,7 @@ import jsPsychHtmlKeyboardSlider from '@jspsych-contrib/plugin-html-keyboard-sli ## Compatibility -jsPsych 7.0.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-html-keyboard-slider/docs/html-keyboard-slider.md b/packages/plugin-html-keyboard-slider/docs/html-keyboard-slider.md index 36f047ee..a4274f78 100644 --- a/packages/plugin-html-keyboard-slider/docs/html-keyboard-slider.md +++ b/packages/plugin-html-keyboard-slider/docs/html-keyboard-slider.md @@ -4,7 +4,7 @@ HTML slider which allows for keyboard responses, with a few extra parameters. ## Parameters -In addition to the [parameters available in all plugins](https://jspsych.org/latest/overview/plugins.md#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ------------------- | ---------------- | ------------------ | ---------------------------------------- | | min | INT | 0 | Slider minimum value. Can be an integer or a float. | @@ -39,7 +39,7 @@ In addition to the [parameters available in all plugins](https://jspsych.org/lat ## Data Generated -In addition to the [default data collected by all plugins](https://jspsych.org/latest/overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Description | | -------------- | -------- | -------------------------------------- | diff --git a/packages/plugin-html-keyboard-slider/src/index.ts b/packages/plugin-html-keyboard-slider/src/index.ts index c4423bbe..f7129d55 100644 --- a/packages/plugin-html-keyboard-slider/src/index.ts +++ b/packages/plugin-html-keyboard-slider/src/index.ts @@ -236,7 +236,7 @@ const info = { type: ParameterType.FLOAT, }, /** - * Stimulus presented + * Stimulus presented. */ stimulus: { type: ParameterType.HTML_STRING, @@ -259,8 +259,7 @@ type Info = typeof info; * * @author Max Lovell * @see {@link https://github.com/jspsych/jspsych-contrib/packages/plugin-html-keyboard-slider/README.md}} - - */ + */ class HtmlKeyboardSliderPlugin implements JsPsychPlugin { static info = info; private keyboardListener: any; // Allows this.keyboardListener id to be saved diff --git a/packages/plugin-html-multi-response/README.md b/packages/plugin-html-multi-response/README.md index 1b1954c5..16ec0afb 100644 --- a/packages/plugin-html-multi-response/README.md +++ b/packages/plugin-html-multi-response/README.md @@ -2,7 +2,7 @@ ## Overview -This plugin displays HTML content and records responses generated by both button click and the keyboard. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays HTML content and records responses generated by both button click and the keyboard. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. ## Loading @@ -12,7 +12,7 @@ This plugin displays HTML content and records responses generated by both button ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.2 of this plugin. ## Documentation diff --git a/packages/plugin-html-multi-response/docs/jspsych-html-multi-response.md b/packages/plugin-html-multi-response/docs/jspsych-html-multi-response.md index 0e96ad45..69f3c78d 100644 --- a/packages/plugin-html-multi-response/docs/jspsych-html-multi-response.md +++ b/packages/plugin-html-multi-response/docs/jspsych-html-multi-response.md @@ -1,34 +1,34 @@ # jspsych-html-multi-response plugin -This plugin displays HTML content and records responses generated by both button click and the keyboard. Allowing multiple response modalities is useful when designing assessments that will be administered on both desktop and mobile (e.g., phone or tablet) devices. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays HTML content and records responses generated by both button click and the keyboard. Allowing multiple response modalities is useful when designing assessments that will be administered on both desktop and mobile (e.g., phone or tablet) devices. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ----------|------|---------------|------------ | | stimulus | HTML string | `undefined` | The HTML content to be displayed. | | button_choices | array of strings | [] | Labels for the buttons. Each different string in the array will generate a different button. | -| keyboard_choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the subject is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | +| keyboard_choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | | button_html | HTML string | `''` | A template of HTML for generating the button elements. You can override this to create customized buttons of various kinds. The string `%choice%` will be changed to the corresponding element of the `choices` array. You may also specify an array of strings, if you need different HTML to render for each button. If you do specify an array, the `choices` array and this array must have the same length. The HTML from position 0 in the `button_html` array will be used to create the button for element 0 in the `choices` array, and so on. | -| prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the subject is supposed to take (e.g., which key to press). | -| trial_duration | numeric | null | How long to wait for the subject to make a response before ending the trial in milliseconds. If the subject fails to make a response before this timer is reached, the subject's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | +| prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). | +| trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | | stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. | | margin_vertical | string | '0px' | Vertical margin of the button(s). | | margin_horizontal | string | '8px' | Horizontal margin of the button(s). | -| response_ends_trial | boolean | true | If true, then the trial will end whenever the subject makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the subject to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | +| response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | -| keyboard_response | string | Indicates which key the subject pressed. If the subject responded using button clicks, then this field will be `null`. | -| button_response | numeric | Indicates which button the subject pressed. The first button in the `choices` array is 0, the second is 1, and so on. If the subject responded using the keyboard, then this field will be `null`. | +| keyboard_response | string | Indicates which key the participant pressed. If the participant responded using button clicks, then this field will be `null`. | +| button_response | numeric | Indicates which button the participant pressed. The first button in the `choices` array is 0, the second is 1, and so on. If the participant responded using the keyboard, then this field will be `null`. | | response_source | string | Indicates the source of the response. This will either be `"button"` or `"keyboard"`. | -| rt | numeric | The response time in milliseconds for the subject to make a response. The time is measured from when the stimulus first appears on the screen until the subject's response. | +| rt | numeric | The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. | | stimulus | string | The HTML content that was displayed on the screen. | ## Example diff --git a/packages/plugin-html-multi-response/src/index.ts b/packages/plugin-html-multi-response/src/index.ts index 6557cf52..c10fa1f5 100644 --- a/packages/plugin-html-multi-response/src/index.ts +++ b/packages/plugin-html-multi-response/src/index.ts @@ -18,7 +18,7 @@ const info = { array: true, }, /** - * Array containing the key(s) the subject is allowed to press to respond to the stimulus. + * Array containing the key(s) the participant is allowed to press to respond to the stimulus. */ keyboard_choices: { type: ParameterType.KEYS, @@ -88,15 +88,15 @@ const info = { type: ParameterType.STRING, }, /** - * Indicates which button the subject pressed. The first button in the `choices` array is 0, the second is 1, and so on. - * If the subject responded using the keyboard, then this field will be `null`. + * Indicates which button the participant pressed. The first button in the `choices` array is 0, the second is 1, and so on. + * If the participant responded using the keyboard, then this field will be `null`. */ button_response: { type: ParameterType.INT, }, /** - * Indicates which key the subject pressed. - * If the subject responded using button clicks, then this field will be `null`. + * Indicates which key the participant pressed. + * If the participant responded using button clicks, then this field will be `null`. */ keyboard_response: { type: ParameterType.STRING, @@ -150,7 +150,7 @@ class HtmlMultiResponsePlugin implements JsPsychPlugin { } display_element.innerHTML = html; - // function to handle responses by the subject + // function to handle responses by the participant var after_keyboard_response = function (info) { // after a valid response, the stimulus will have the CSS class 'responded' // which can be used to provide visual feedback that a response was recorded @@ -224,7 +224,7 @@ class HtmlMultiResponsePlugin implements JsPsychPlugin { this.jsPsych.finishTrial(trial_data); }; - // function to handle responses by the subject + // function to handle responses by the participant function after_response(choice: string) { // measure rt var end_time = performance.now(); diff --git a/packages/plugin-html-swipe-response/README.md b/packages/plugin-html-swipe-response/README.md index 88137f9e..48ce0659 100644 --- a/packages/plugin-html-swipe-response/README.md +++ b/packages/plugin-html-swipe-response/README.md @@ -2,7 +2,7 @@ ## Overview -This plugin displays HTML content and records responses generated by swipe gestures, keyboard, and button responses. This is ideal for two-alternative forced choice assessments that will be administered on both mobile and desktop platforms. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays HTML content and records responses generated by swipe gestures, keyboard, and button responses. This is ideal for two-alternative forced choice assessments that will be administered on both mobile and desktop platforms. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. Setting the `stimulus_duration` parameter while using the swipe modality can result in a user experience issue, wherein the user must swipe a stimulus div tag that has been hidden after the stimulus duration has elapsed. To solve this, this plugin wraps the stimulus div tag in another tag with the ID `#jspsych-html-swipe-response-stimulus-container`. This div tag can then be styled so that they user has some visual representation of the stimulus even after the `#jspsych-html-swipe-response-stimulus-container` div has been hidden. @@ -14,7 +14,7 @@ Setting the `stimulus_duration` parameter while using the swipe modality can res ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.1.2 of this plugin. ## Documentation diff --git a/packages/plugin-html-swipe-response/docs/jspsych-html-swipe-response.md b/packages/plugin-html-swipe-response/docs/jspsych-html-swipe-response.md index 480fd696..00c60ce8 100644 --- a/packages/plugin-html-swipe-response/docs/jspsych-html-swipe-response.md +++ b/packages/plugin-html-swipe-response/docs/jspsych-html-swipe-response.md @@ -1,41 +1,41 @@ # jspsych-html-swipe-response plugin -This plugin displays HTML content and records responses generated by swipe gestures, keyboard, and button responses. This plugin will be useful for two-alternative forced choice (2AFC) assessments that will be administered on both desktop and mobile devices. The stimulus can be animated to move off-screen before the trial ends. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. After the user responds a `'responded'` css class gets added to the stimulus and to the button corresponding to their choice. +This plugin displays HTML content and records responses generated by swipe gestures, keyboard, and button responses. This plugin will be useful for two-alternative forced choice (2AFC) assessments that will be administered on both desktop and mobile devices. The stimulus can be animated to move off-screen before the trial ends. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. After the user responds a `'responded'` css class gets added to the stimulus and to the button corresponding to their choice. Setting the `stimulus_duration` parameter while using the swipe modality can result in a user experience issue, wherein the user must swipe a stimulus div tag that has been hidden after the stimulus duration has elapsed. To solve this, this plugin wraps the stimulus div tag in another tag with the ID `#jspsych-html-swipe-response-stimulus-container`. This div tag can then be styled so that they user has some visual representation of the stimulus even after the `#jspsych-html-swipe-response-stimulus-container` div has been hidden. ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ----------|------|---------------|------------ | | stimulus | HTML string | `undefined` | The HTML content to be displayed. | | button_choices | array of strings | [] | Labels for the buttons. Each different string in the array will generate a different button. | -| keyboard_choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the subject is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | +| keyboard_choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | button_html | HTML string | `''` | A template of HTML for generating the button elements. You can override this to create customized buttons of various kinds. The string `%choice%` will be changed to the corresponding element of the `choices` array. You may also specify an array of strings, if you need different HTML to render for each button. If you do specify an array, the `choices` array and this array must have the same length. The HTML from position 0 in the `button_html` array will be used to create the button for element 0 in the `choices` array, and so on. | -| prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the subject is supposed to take (e.g., which key to press). | +| prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). | | stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. | -| trial_duration | numeric | null | How long to wait for the subject to make a response before ending the trial in milliseconds. If the subject fails to make a response before this timer is reached, the subject's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | +| trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | | margin_vertical | string | '0px' | Vertical margin of the button(s). | | margin_horizontal | string | '8px' | Horizontal margin of the button(s). | -| response_ends_trial | boolean | true | If true, then the trial will end whenever the subject makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the subject to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | -| swipe_threshold | numeric | 20 | How far away from the center should the subject have to swipe for a left/right response to be recorded. If the subject releases their finger before this threshold, the stimulus will return to the neutral center position. If the subject exceeds this threshold, the swipe response will be recorded. | +| response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | +| swipe_threshold | numeric | 20 | How far away from the center should the participant have to swipe for a left/right response to be recorded. If the participant releases their finger before this threshold, the stimulus will return to the neutral center position. If the participant exceeds this threshold, the swipe response will be recorded. | | swipe_offscreen_coordinate | numeric | 1000 | The offscreen coordinate for the swipe animation. | -| swipe_animation_max_rotation | numeric | 20 | How much should the swipe animation rotate the stimulus (in degrees). When the subject drags to the left (right), the stimulus will rotate slightly clockwise (counter-clockwise). */ +| swipe_animation_max_rotation | numeric | 20 | How much should the swipe animation rotate the stimulus (in degrees). When the participant drags to the left (right), the stimulus will rotate slightly clockwise (counter-clockwise). */ | swipe_animation_duration | numeric | 250 | How long should the swipe animation last in milliseconds. Set this to zero to disable the animation. This animation time will not be included in the reaction time. | ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | -| keyboard_response | string | Indicates which key the subject pressed. If the subject responded using button clicks, then this field will be `null`. | -| button_response | numeric | Indicates which button the subject pressed. The first button in the `choices` array is 0, the second is 1, and so on. If the subject responded using the keyboard, then this field will be `null`. | -| swipe_response | string | Indicates which direction the subject swiped. This will be either `"left"` or `"right"`. If the subject responded using the keyboard, then this field will be `null`. | +| keyboard_response | string | Indicates which key the participant pressed. If the participant responded using button clicks, then this field will be `null`. | +| button_response | numeric | Indicates which button the participant pressed. The first button in the `choices` array is 0, the second is 1, and so on. If the participant responded using the keyboard, then this field will be `null`. | +| swipe_response | string | Indicates which direction the participant swiped. This will be either `"left"` or `"right"`. If the participant responded using the keyboard, then this field will be `null`. | | response_source | string | Indicates the source of the response. This will either be `"swipe"`, `"keyboard"`, or `"button"`. | -| rt | numeric | The response time in milliseconds for the subject to make a response. The time is measured from when the stimulus first appears on the screen until the subject's response. | +| rt | numeric | The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. | | stimulus | string | The HTML content that was displayed on the screen. | ## Example diff --git a/packages/plugin-html-swipe-response/src/index.ts b/packages/plugin-html-swipe-response/src/index.ts index 2b2dfa8a..22778c0b 100644 --- a/packages/plugin-html-swipe-response/src/index.ts +++ b/packages/plugin-html-swipe-response/src/index.ts @@ -18,7 +18,7 @@ const info = { default: [], array: true, }, - /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */ + /** Array containing the key(s) the participant is allowed to press to respond to the stimulus. */ keyboard_choices: { type: ParameterType.KEYS, pretty_name: "Keyboard Choices", @@ -67,13 +67,13 @@ const info = { pretty_name: "Margin horizontal", default: "8px", }, - /** If true, trial will end when subject makes a response. */ + /** If true, trial will end when participant makes a response. */ response_ends_trial: { type: ParameterType.BOOL, pretty_name: "Response ends trial", default: true, }, - /** How far away from the center should the subject have to swipe for a + /** How far away from the center should the participant have to swipe for a * left/right response to be recorded. */ swipe_threshold: { type: ParameterType.INT, @@ -114,22 +114,22 @@ const info = { type: ParameterType.STRING, }, /** - * Indicates which button the subject pressed. The first button in the `choices` array is 0, the second is 1, and so on. - * If the subject responded using the keyboard, then this field will be `null`. + * Indicates which button the participant pressed. The first button in the `choices` array is 0, the second is 1, and so on. + * If the participant responded using the keyboard, then this field will be `null`. */ button_response: { type: ParameterType.INT, }, /** - * Indicates which key the subject pressed. - * If the subject responded using button clicks, then this field will be `null`. + * Indicates which key the participant pressed. + * If the participant responded using button clicks, then this field will be `null`. */ keyboard_response: { type: ParameterType.STRING, }, /** - * Indicates which direction the subject swiped. - * This will be either `"left"` or `"right"`. If the subject responded using the keyboard, + * Indicates which direction the participant swiped. + * This will be either `"left"` or `"right"`. If the participant responded using the keyboard, * then this field will be `null`. */ swipe_response: { @@ -289,7 +289,7 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { }); }; - // function to handle swipe responses by the subject + // function to handle swipe responses by the participant const after_swipe_response = (left_or_right: "left" | "right") => { if (left_or_right !== null) { // measure rt @@ -342,7 +342,7 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { }, }); - // function to handle responses by the subject + // function to handle responses by the participant const after_keyboard_response = (info) => { // only record the first response if (response.key == null) { @@ -372,7 +372,7 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { } }; - // function to handle responses by the subject + // function to handle responses by the participant const after_button_response = (choice: string) => { // measure rt var end_time = performance.now(); diff --git a/packages/plugin-html-vas-response/README.md b/packages/plugin-html-vas-response/README.md index e3ba933c..980a3a08 100644 --- a/packages/plugin-html-vas-response/README.md +++ b/packages/plugin-html-vas-response/README.md @@ -12,7 +12,7 @@ This plugin collects responses to an arbitrary HTML string using a point-and-cli ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.2.0 of this plugin. ## Documentation diff --git a/packages/plugin-html-vas-response/docs/jspsych-html-vas-response.md b/packages/plugin-html-vas-response/docs/jspsych-html-vas-response.md index 6a65ce89..3a68bc4f 100644 --- a/packages/plugin-html-vas-response/docs/jspsych-html-vas-response.md +++ b/packages/plugin-html-vas-response/docs/jspsych-html-vas-response.md @@ -8,7 +8,7 @@ Kinley, I. (2022, March 7). "A jsPsych plugin for visual analogue scales." Retri ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Descripton | | ------------------------ | ---------------- | -------------------- | ---------------------------------------- | @@ -32,7 +32,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. | Name | Type | Value | | ---------------- | ----------- | ---------------------------------------- | diff --git a/packages/plugin-image-array-keyboard-response/docs/jspsych-image-array-keyboard-response.md b/packages/plugin-image-array-keyboard-response/docs/jspsych-image-array-keyboard-response.md index df3b75f7..51fc5dd1 100644 --- a/packages/plugin-image-array-keyboard-response/docs/jspsych-image-array-keyboard-response.md +++ b/packages/plugin-image-array-keyboard-response/docs/jspsych-image-array-keyboard-response.md @@ -1,31 +1,31 @@ # jspsych-image-array-keyboard-response plugin -This plugin displays images and records responses generated with the keyboard. The position and size of the images can be specified. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays images and records responses generated with the keyboard. The position and size of the images can be specified. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | |-----------------------------|------------------| ------------------ |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | stimulus | array of string | *undefined* | The path of the image files to be displayed. | | stimulus_rect | array of integer | null | Set the positionX, positionY, width, and height of the images in pixels. If width and height are left null, then the image will display at its natural height. | | maintain_aspect_ratio | boolean | true | If setting *only* the width or *only* the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. | -| choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the subject is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | +| choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. | -| trial_duration | numeric | null | How long to wait for the subject to make a response before ending the trial in milliseconds. If the subject fails to make a response before this timer is reached, the subject's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | -| response_ends_trial | boolean | true | If true, then the trial will end whenever the subject makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the subject to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | +| trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | +| response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | | render_on_canvas | boolean | true | If `true`, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If `false`, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an **animated gif**, you must set this parameter to false, because the canvas rendering method will only present static images. | ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| keyboard_response | string | Indicates which key the subject pressed. If the subject responded using button clicks, then this field will be `null`. | -| rt | numeric | The response time in milliseconds for the subject to make a response. The time is measured from when the stimulus first appears on the screen until the subject's response. | +| response | string | Indicates which key the participant pressed. If the participant responded using button clicks, then this field will be `null`. | +| rt | numeric | The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. | | stimulus | string | The paths of the images that were displayed on the screen. | ## Example diff --git a/packages/plugin-image-array-keyboard-response/readme.md b/packages/plugin-image-array-keyboard-response/readme.md index 8bdc3f36..e1949ab7 100644 --- a/packages/plugin-image-array-keyboard-response/readme.md +++ b/packages/plugin-image-array-keyboard-response/readme.md @@ -2,7 +2,7 @@ ## Overview -This plugin displays images and records responses generated with the keyboard. The position and size of the images can be specified. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays images and records responses generated with the keyboard. The position and size of the images can be specified. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. ## Loading @@ -25,7 +25,7 @@ import jsPsychImageArrayKeyboardResponse from '@jspsych-contrib/plugin-image-arr ## Compatibility -jsPsych v7.0. +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-image-array-keyboard-response/src/index.ts b/packages/plugin-image-array-keyboard-response/src/index.ts index f1ad016c..c90e528b 100644 --- a/packages/plugin-image-array-keyboard-response/src/index.ts +++ b/packages/plugin-image-array-keyboard-response/src/index.ts @@ -25,7 +25,7 @@ const info = { pretty_name: "Maintain aspect ratio", default: true, }, - /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */ + /** Array containing the key(s) the participant is allowed to press to respond to the stimulus. */ choices: { type: ParameterType.KEYS, pretty_name: "Choices", @@ -43,7 +43,7 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** If true, trial will end when subject makes a response. */ + /** If true, trial will end when participant makes a response. */ response_ends_trial: { type: ParameterType.BOOL, pretty_name: "Response ends trial", @@ -70,7 +70,7 @@ const info = { type: ParameterType.STRING, array: true, }, - /** The key that the subject pressed. */ + /** The key that the participant pressed. */ response: { type: ParameterType.STRING, }, @@ -232,7 +232,7 @@ class ImageArrayKeyboardResponsePlugin implements JsPsychPlugin { this.jsPsych.finishTrial(trial_data); }; - // function to handle responses by the subject + // function to handle responses by the participant var after_response = (info) => { // after a valid response, the stimulus will have the CSS class 'responded' // which can be used to provide visual feedback that a response was recorded diff --git a/packages/plugin-image-multi-response/README.md b/packages/plugin-image-multi-response/README.md index ce190fd7..23d12bbb 100644 --- a/packages/plugin-image-multi-response/README.md +++ b/packages/plugin-image-multi-response/README.md @@ -2,7 +2,7 @@ ## Overview -This plugin displays image content and records responses generated by both button click and the keyboard.The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays image content and records responses generated by both button click and the keyboard.The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. ## Loading @@ -12,7 +12,7 @@ This plugin displays image content and records responses generated by both butto ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.1 of this plugin. ## Documentation diff --git a/packages/plugin-image-multi-response/docs/jspsych-image-multi-response.md b/packages/plugin-image-multi-response/docs/jspsych-image-multi-response.md index 58604792..3d4d33db 100644 --- a/packages/plugin-image-multi-response/docs/jspsych-image-multi-response.md +++ b/packages/plugin-image-multi-response/docs/jspsych-image-multi-response.md @@ -1,34 +1,34 @@ # jspsych-image-multi-response plugin -This plugin displays image content and records responses generated by both button click and the keyboard. Allowing multiple response modalities is useful when designing assessments that will be administered on both desktop and mobile (e.g., phone or tablet) devices. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays image content and records responses generated by both button click and the keyboard. Allowing multiple response modalities is useful when designing assessments that will be administered on both desktop and mobile (e.g., phone or tablet) devices. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ----------|------|---------------|------------ | | stimulus | HTML string | `undefined` | The HTML content to be displayed. | | button_choices | array of strings | [] | Labels for the buttons. Each different string in the array will generate a different button. | -| keyboard_choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the subject is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | +| keyboard_choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | | button_html | function | ``(choice: string, choice_index: number) => `;` `` | A function that generates the HTML for each button in the `choices` array. The function gets the string and index of the item in the `choices` array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. | -| prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the subject is supposed to take (e.g., which key to press). | -| trial_duration | numeric | null | How long to wait for the subject to make a response before ending the trial in milliseconds. If the subject fails to make a response before this timer is reached, the subject's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | +| prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). | +| trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | | stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. | | margin_vertical | string | '0px' | Vertical margin of the button(s). | | margin_horizontal | string | '8px' | Horizontal margin of the button(s). | -| response_ends_trial | boolean | true | If true, then the trial will end whenever the subject makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the subject to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | +| response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | -| keyboard_response | string | Indicates which key the subject pressed. If the subject responded using button clicks, then this field will be `null`. | -| button_response | numeric | Indicates which button the subject pressed. The first button in the `choices` array is 0, the second is 1, and so on. If the subject responded using the keyboard, then this field will be `null`. | +| keyboard_response | string | Indicates which key the participant pressed. If the participant responded using button clicks, then this field will be `null`. | +| button_response | numeric | Indicates which button the participant pressed. The first button in the `choices` array is 0, the second is 1, and so on. If the participant responded using the keyboard, then this field will be `null`. | | response_source | string | Indicates the source of the response. This will either be `"button"` or `"keyboard"`. | -| rt | numeric | The response time in milliseconds for the subject to make a response. The time is measured from when the stimulus first appears on the screen until the subject's response. | +| rt | numeric | The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. | | stimulus | string | The HTML content that was displayed on the screen. | ## Example diff --git a/packages/plugin-image-multi-response/src/index.ts b/packages/plugin-image-multi-response/src/index.ts index f3f08169..77008238 100644 --- a/packages/plugin-image-multi-response/src/index.ts +++ b/packages/plugin-image-multi-response/src/index.ts @@ -35,7 +35,7 @@ const info = { default: [], array: true, }, - /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */ + /** Array containing the key(s) the participant is allowed to press to respond to the stimulus. */ keyboard_choices: { type: ParameterType.KEYS, pretty_name: "Keyboard Choices", @@ -113,15 +113,15 @@ const info = { type: ParameterType.STRING, }, /** - * Indicates which button the subject pressed. The first button in the `choices` array is 0, the second is 1, and so on. - * If the subject responded using the keyboard, then this field will be `null`. + * Indicates which button the participant pressed. The first button in the `choices` array is 0, the second is 1, and so on. + * If the participant responded using the keyboard, then this field will be `null`. */ button_response: { type: ParameterType.INT, }, /** - * Indicates which key the subject pressed. - * If the subject responded using button clicks, then this field will be `null`. + * Indicates which key the participant pressed. + * If the participant responded using button clicks, then this field will be `null`. */ keyboard_response: { type: ParameterType.STRING, @@ -290,7 +290,7 @@ class ImageMultiResponsePlugin implements JsPsychPlugin { img.style.width = width.toString() + "px"; } - // function to handle responses by the subject + // function to handle responses by the participant var after_keyboard_response = function (info) { // after a valid response, the stimulus will have the CSS class 'responded' // which can be used to provide visual feedback that a response was recorded @@ -364,7 +364,7 @@ class ImageMultiResponsePlugin implements JsPsychPlugin { this.jsPsych.finishTrial(trial_data); }; - // function to handle responses by the subject + // function to handle responses by the participant function after_response(choice: string) { // measure rt var end_time = performance.now(); diff --git a/packages/plugin-image-swipe-response/README.md b/packages/plugin-image-swipe-response/README.md index 215a7577..832fbd7c 100644 --- a/packages/plugin-image-swipe-response/README.md +++ b/packages/plugin-image-swipe-response/README.md @@ -2,7 +2,7 @@ ## Overview -This plugin displays image content and records responses generated by both swipe gestures and keyboard response. This is ideal for two-alternative forced choice assessments that will be administered on both mobile and desktop platforms. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays image content and records responses generated by both swipe gestures and keyboard response. This is ideal for two-alternative forced choice assessments that will be administered on both mobile and desktop platforms. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. ## Loading @@ -12,7 +12,7 @@ This plugin displays image content and records responses generated by both swipe ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-image-swipe-response/docs/jspsych-image-swipe-response.md b/packages/plugin-image-swipe-response/docs/jspsych-image-swipe-response.md index de0bff56..b0ec0007 100644 --- a/packages/plugin-image-swipe-response/docs/jspsych-image-swipe-response.md +++ b/packages/plugin-image-swipe-response/docs/jspsych-image-swipe-response.md @@ -1,10 +1,10 @@ # jspsych-image-swipe-response plugin -This plugin displays image content and records responses generated by both swipe gestures and keyboard response. This plugin will be useful for two-alternative forced choice (2AFC) assessments that will be administered on both desktop and mobile devices. The stimulus can be animated to move off-screen before the trial ends. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the subject has failed to respond within a fixed length of time. +This plugin displays image content and records responses generated by both swipe gestures and keyboard response. This plugin will be useful for two-alternative forced choice (2AFC) assessments that will be administered on both desktop and mobile devices. The stimulus can be animated to move off-screen before the trial ends. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | --------------------- | ---------------- | ------------------ | ---------------------------------------- | @@ -12,27 +12,27 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org | stimulus_height | integer | null | Set the height of the image in pixels. If left null (no value specified), then the image will display at its natural height. | | stimulus_width | integer | null | Set the width of the image in pixels. If left null (no value specified), then the image will display at its natural width. | | maintain_aspect_ratio | boolean | true | If setting *only* the width or *only* the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. | -| keyboard_choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the subject is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | -| prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the subject is supposed to take (e.g., which key to press). | +| keyboard_choices | array of strings | `"NO_KEYS"` | This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. Specifying `"ALL_KEYS"` means that all keys will be accepted as valid responses. The default value of `"NO_KEYS"` will mean that no responses are allowed. | | +| prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). | | stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. | -| trial_duration | numeric | null | How long to wait for the subject to make a response before ending the trial in milliseconds. If the subject fails to make a response before this timer is reached, the subject's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | -| response_ends_trial | boolean | true | If true, then the trial will end whenever the subject makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the subject to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | -| swipe_threshold | numeric | 20 | How far away from the center should the subject have to swipe for a left/right response to be recorded. If the subject releases their finger before this threshold, the stimulus will return to the neutral center position. If the subject exceeds this threshold, the swipe response will be recorded. | +| trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | +| response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. | +| swipe_threshold | numeric | 20 | How far away from the center should the participant have to swipe for a left/right response to be recorded. If the participant releases their finger before this threshold, the stimulus will return to the neutral center position. If the participant exceeds this threshold, the swipe response will be recorded. | | swipe_offscreen_coordinate | numeric | 1000 | The offscreen coordinate for the swipe animation. | -| swipe_animation_max_rotation | numeric | 20 | How much should the swipe animation rotate the stimulus (in degrees). When the subject drags to the left (right), the stimulus will rotate slightly clockwise (counter-clockwise). */ +| swipe_animation_max_rotation | numeric | 20 | How much should the swipe animation rotate the stimulus (in degrees). When the participant drags to the left (right), the stimulus will rotate slightly clockwise (counter-clockwise). */ | swipe_animation_duration | numeric | 250 | How long should the swipe animation last in milliseconds. Set this to zero to disable the animation. This animation time will not be included in the reaction time. | | render_on_canvas | boolean | true | If `true`, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If `false`, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an **animated gif**, you must set this parameter to false, because the canvas rendering method will only present static images. | ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | -| keyboard_response | string | Indicates which key the subject pressed. If the subject responded using button clicks, then this field will be `null`. | -| swipe_response | string | Indicates which direction the subject swiped. This will be either `"left"` or `"right"`. If the subject responded using the keyboard, then this field will be `null`. | +| keyboard_response | string | Indicates which key the participant pressed. If the participant responded using button clicks, then this field will be `null`. | +| swipe_response | string | Indicates which direction the participant swiped. This will be either `"left"` or `"right"`. If the participant responded using the keyboard, then this field will be `null`. | | response_source | string | Indicates the source of the response. This will either be `"swipe"` or `"keyboard"`. | -| rt | numeric | The response time in milliseconds for the subject to make a response. The time is measured from when the stimulus first appears on the screen until the subject's response. | +| rt | numeric | The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. | | stimulus | string | The HTML content that was displayed on the screen. | ## Example diff --git a/packages/plugin-image-swipe-response/src/index.ts b/packages/plugin-image-swipe-response/src/index.ts index 567f1c4f..c9bcc6e2 100644 --- a/packages/plugin-image-swipe-response/src/index.ts +++ b/packages/plugin-image-swipe-response/src/index.ts @@ -29,7 +29,7 @@ const info = { pretty_name: "Maintain aspect ratio", default: true, }, - /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */ + /** Array containing the key(s) the participant is allowed to press to respond to the stimulus. */ keyboard_choices: { type: ParameterType.KEYS, pretty_name: "Keyboard Choices", @@ -53,13 +53,13 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** If true, trial will end when subject makes a response. */ + /** If true, trial will end when participant makes a response. */ response_ends_trial: { type: ParameterType.BOOL, pretty_name: "Response ends trial", default: true, }, - /** How far away from the center should the subject have to swipe for a + /** How far away from the center should the participant have to swipe for a * left/right response to be recorded. */ swipe_threshold: { type: ParameterType.INT, @@ -107,12 +107,12 @@ const info = { stimulus: { type: ParameterType.STRING, }, - /** Indicates which key the subject pressed. If the subject responded using button clicks, + /** Indicates which key the participant pressed. If the participant responded using button clicks, * then this field will be `null`. */ keyboard_response: { type: ParameterType.STRING, }, - /** Indicates which direction the subject swiped. If the subject responded using the keyboard, + /** Indicates which direction the participant swiped. If the participant responded using the keyboard, * then this field will be `null`. */ swipe_response: { type: ParameterType.STRING, @@ -301,7 +301,7 @@ class ImageSwipeResponsePlugin implements JsPsychPlugin { " responded"; }; - // function to handle swipe responses by the subject + // function to handle swipe responses by the participant const after_swipe_response = (left_or_right: "left" | "right") => { toggle_css_respond(); @@ -351,7 +351,7 @@ class ImageSwipeResponsePlugin implements JsPsychPlugin { }, }); - // function to handle responses by the subject + // function to handle responses by the participant const after_keyboard_response = (info) => { toggle_css_respond(); diff --git a/packages/plugin-ios/README.md b/packages/plugin-ios/README.md index d76844bd..7f98d693 100644 --- a/packages/plugin-ios/README.md +++ b/packages/plugin-ios/README.md @@ -12,7 +12,7 @@ This plugin allows for continuous responses on the Inclusion of Other in the Sel ## Compatibility -jsPsych v8.0. For using jsPsych v7.0, use version 1.0.0. +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-ios/docs/jspsych-ios.md b/packages/plugin-ios/docs/jspsych-ios.md index 6e6839f8..7c761935 100644 --- a/packages/plugin-ios/docs/jspsych-ios.md +++ b/packages/plugin-ios/docs/jspsych-ios.md @@ -4,17 +4,20 @@ This plugin allows for continuous responses on the Inclusion of Other in the Sel ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Descripton | | ------------------------ | ---------------- | -------------------- | ---------------------------------------- | | prompt | HTML string | `undefined` | The prompt to be displayed above the circles. | -| [left/right]_label | HTML string | `undefined` | The label for the left/right circle | -| max_sep | integer | 0 | The maximum allowable separation between the two circles. | -| ticks | Boolean | `true` | Specifies whether smaller vertical tick marks should accompany the labels. | -| [left/right]_border_width | integer | 2 | Width, in pixels, of the [left/right] circle's border. | -| [left/right]_border_style | string | `'solid'` | Style argument for the [left/right] circle's border. | -| [left/right]_border_colour | string | `'black'` | Colour argument for the [left/right] circle's border. | +| movable_circle | string | `right` | Specifies which circle `left` or `right` may be moved by the participant. | +| both_move | Boolean | `true` | Specifies if both circles move (`true`), or just one of them (`false`). | +| front_circle | string | `right` | Specifies which circle is in front of the other. | +| [left/right]_label | HTML string | `undefined` | The label for the left/right circle. | +| [left/right]_diam | integer | 200 | The diameter for the left/right circle, in pixels. | +| max_sep | integer | 0 | The maximum allowable separation between the two circles. | +| [left/right]_border_width | integer | 2 | Width, in pixels, of the [left/right] circle's border. | +| [left/right]_border_style | string | `'solid'` | Style argument for the [left/right] circle's border. | +| [left/right]_border_colour | string | `'black'` | Colour argument for the [left/right] circle's border. | | [left/right]_style | string | `''` | Additional style arguments for the [left/right] circle. E.g., `'background-color: rgba(1, 0, 0, 0.5)';` | | arrows | Boolean | `false` | Specifies whether lines should connect the circles to their labels, in case of any ambiguity (e.g., if one circle is smaller). | | cursor | string | `'crosshair'` | Style of cursor when the user hovers over the clickable area. | @@ -24,13 +27,13 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. -| Name | Type | Value | -| ---------------- | ----------- | ---------------------------------------- | -| response | numeric | The degree of overlap selected, where 1 means the circles are concentric, 0 means the circles have no overlap but no space between them, and negative numbers reflect separation between the circles (measured on the same scale as positive numbers representing overlap). Note that this number scales linearly, meaning it is not a measure of the overlapping area of the circles. | -| rt | numeric | The time in milliseconds, between when the trial began and when the paticipant clicked the continue button. | -| prompt | string | The prompt displayed during the trial. | +| Name | Type | Value | +| ---------------- | --------- | ---------------------------------------- | +| response | numeric | The degree of overlap selected, where 1 means the circles are concentric, 0 means the circles have no overlap but no space between them, and negative numbers reflect separation between the circles (measured on the same scale as positive numbers representing overlap). Note that this number scales linearly, meaning it is not a measure of the overlapping area of the circles. | +| rt | numeric | The time in milliseconds, between when the trial began and when the paticipant clicked the continue button. | +| prompt | string | The prompt displayed during the trial. | ## Examples diff --git a/packages/plugin-ios/index.js b/packages/plugin-ios/index.js index 9127cda6..e7452f3f 100644 --- a/packages/plugin-ios/index.js +++ b/packages/plugin-ios/index.js @@ -5,111 +5,133 @@ var jsPsychIos = (function (jspsych) { name: "ios", version: "2.0.0", parameters: { + /** The prompt to be displayed above the circles. */ prompt: { type: jspsych.ParameterType.HTML_STRING, pretty_name: "Prompt", default: undefined, }, + /** Specifies which circle `left` or `right` may be moved by the participant. */ movable_circle: { type: jspsych.ParameterType.STRING, pretty_name: "Movable circle", default: "right", }, + /** Specifies if both circles move (`true`), or just one of them (`false`). */ both_move: { type: jspsych.ParameterType.BOOL, pretty_name: "Both circles move?", default: "one", }, + /** Specifies which circle is in front of the other. */ front_circle: { type: jspsych.ParameterType.STRING, pretty_name: "Front circle", default: "right", }, + /** Label for the left circle. */ left_label: { type: jspsych.ParameterType.HTML_STRING, pretty_name: "Left circle label", default: "[left_label]", }, + /** Label for the right circle. */ right_label: { type: jspsych.ParameterType.HTML_STRING, pretty_name: "Right circle label", default: "[right_label]", }, + /** Diameter of the left circle, in pixels. */ left_diam: { type: jspsych.ParameterType.INT, pretty_name: "Left circle diameter", default: 200, }, + /** Diameter of the right circle, in pixels. */ right_diam: { type: jspsych.ParameterType.INT, pretty_name: "Right circle diameter", default: 200, }, + /** The maximum allowable separation between the two circles. */ max_sep: { type: jspsych.ParameterType.INT, pretty_name: "Maximum separation", default: 0, }, + /** Width, in pixels, of the left circle's border. */ left_border_width: { type: jspsych.ParameterType.INT, pretty_name: "Left circle border width", default: 2, }, + /** Style arguments for the left circle's border. */ left_border_style: { type: jspsych.ParameterType.STRING, pretty_name: "Left circle border style", default: "solid", }, + /** Colour of the left circle's border. */ left_border_col: { type: jspsych.ParameterType.STRING, pretty_name: "Left circle border colour", default: "black", }, + /** Additional style arguments for the [left/right] circle. E.g., `'background-color: rgba(1, 0, 0, 0.5)';` */ left_style: { type: jspsych.ParameterType.STRING, pretty_name: "Left circle style", default: "", }, + /** Width, in pixels, of the right circle's border. */ right_border_width: { type: jspsych.ParameterType.INT, pretty_name: "Right circle border width", default: 2, }, + /** Style arguments for the right circle's border. */ right_border_style: { type: jspsych.ParameterType.STRING, pretty_name: "Right circle border style", default: "solid", }, + /** Colour of the right circle's border. */ right_border_col: { type: jspsych.ParameterType.STRING, pretty_name: "Right circle border colour", default: "black", }, + /** Additional style arguments for the [left/right] circle. E.g., `'background-color: rgba(1, 0, 0, 0.5)';` */ right_style: { type: jspsych.ParameterType.STRING, pretty_name: "Right circle style", default: "", }, + /** Specifies whether lines should connect the circles to their labels, in case of any ambiguity (e.g., if one circle is smaller). */ arrows: { type: jspsych.ParameterType.BOOL, pretty_name: "Arrows", default: false, }, + /** Style of cursor when the user hovers over the clickable area. */ cursor: { type: jspsych.ParameterType.STRING, pretty_name: "Cursor when circles clickable", default: "crosshair", }, + /** Text of the button the user clicks to submit their response. */ button_label: { type: jspsych.ParameterType.HTML_STRING, - pretty_name: "Buton label", + pretty_name: "Button label", default: "Continue", }, + /** Specifies whether the user must make a response of some kind before clicking the submit button. */ required: { type: jspsych.ParameterType.BOOL, pretty_name: "Response required", default: false, }, + /** If true, the circles are hidden until the user hovers over them. */ hide_initially: { type: jspsych.ParameterType.BOOL, pretty_name: "Hide initially", @@ -126,7 +148,8 @@ var jsPsychIos = (function (jspsych) { prompt: { type: jspsych.ParameterType.HTML_STRING, }, - /** Proportion of the circles that are combined, on a scale from [0, 1]. */ + /** The degree of overlap, with 1 being concentric circles, 0 being no space between but no overlap, + * and negative values indicating the amount of separation. */ response: { type: jspsych.ParameterType.FLOAT, }, diff --git a/packages/plugin-libet-intentional-binding/README.md b/packages/plugin-libet-intentional-binding/README.md index 9c2f1ba0..19cd0f11 100644 --- a/packages/plugin-libet-intentional-binding/README.md +++ b/packages/plugin-libet-intentional-binding/README.md @@ -12,7 +12,7 @@ This plugin measures intentional binding using a Libet clock, and allows the par ## Compatibility -jsPsych v7.0 +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.2.0 of this plugin. ## Documentation diff --git a/packages/plugin-libet-intentional-binding/docs/jspsych-libet-intentional-binding.md b/packages/plugin-libet-intentional-binding/docs/jspsych-libet-intentional-binding.md index f959463b..4464f8b3 100644 --- a/packages/plugin-libet-intentional-binding/docs/jspsych-libet-intentional-binding.md +++ b/packages/plugin-libet-intentional-binding/docs/jspsych-libet-intentional-binding.md @@ -8,7 +8,7 @@ This plugin measures intentional binding using a Libet clock, and allows the par ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Descripton | | ------------------------ | ---------------- | -------------------- | ---------------------------------------- | @@ -28,8 +28,9 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org | fixation_ms | int | 400 | Duration of the pre-trial fixation cross in ms. | | clock_period | int | 2560 | The period of the clock in ms. | | early_ms | int | 2560 | The earliest allowable keypress, measured in milliseconds since the clock hand begins rotating. If a keypress is made prior to this, the trial ends. | -| early_fcn | function | `function(){}` | Function called when the participant responds too early (e.g., to provide feedback). | +| early_fcn | function | `function(){}` | Function called when the participant responds too early (e.g., to provide feedback). | | timeout_ms | int | 4000 | The maximum length of a trial, measured in milliseconds since the clock hand begins rotating. If a keypress is not made prior to this, the trial ends. | +| timeout_fcn | function | `function(){}` | Function called when the the trial times out. | | spin_continue_ms | int | 1000 | The length of time, in ms, after the keypress or tone, whichever comes later, that the clock animation continues. | | clock_diam | int | 200 | The diameter of the clock in pixels. | | n_maj_ticks | int | 60 | The number of major ticks to draw on the clock face. | @@ -46,7 +47,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. | Name | Type | Value | | ---------------- | ----------- | ---------------------------------------- | diff --git a/packages/plugin-libet-intentional-binding/index.js b/packages/plugin-libet-intentional-binding/index.js index 0c9559d8..02c66b17 100644 --- a/packages/plugin-libet-intentional-binding/index.js +++ b/packages/plugin-libet-intentional-binding/index.js @@ -10,7 +10,7 @@ var jsPsychLibetIntentionalBinding = (function (jspsych) { pretty_name: "Condition", default: "baseline-key", description: - 'Specifies whether condition ("baseline-key", "baseline-tone", "operant-key", or "operant-tone".', + 'Specifies the condition ("baseline-key", "baseline-tone", "operant-key", or "operant-tone").', }, est_wo_keypress: { type: jspsych.ParameterType.BOOL, diff --git a/packages/plugin-nextcloud-filedrop/README.md b/packages/plugin-nextcloud-filedrop/README.md index 7c793dfe..7d979324 100644 --- a/packages/plugin-nextcloud-filedrop/README.md +++ b/packages/plugin-nextcloud-filedrop/README.md @@ -36,11 +36,10 @@ import jsPsychNextcloudFiledropPlugin from '@jspsych-contrib/plugin-nextcloud-fi ## Compatibility -This extension was developed for, and tested with jsPsych v7.3.0. +jsPsych v8.0. For compatibility with jsPsych v7.3+, use version 1.0.0 of this plugin. ## Documentation - ### Create File Drop Folder To use the plugin, you need to share a folder using file drop. @@ -59,13 +58,30 @@ The contents of the directory, e.g., previously uploaded files, will not be visi The files will not be overriden. Files with the same filename will automatically be enumerated. -> **_IMPORTANT:_** Please ensure secure data transfer via SSL/TLS encryption, i.e., use https instead of http. +> **_IMPORTANT:_** Please ensure secure data transfer via SSL/TLS encryption, i.e., use https instead of http. ### Trial Parameters -This plugin accepts the following parameters: +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters: + +Parameter | Type | Default Value | Description +----------|------|---------------|------------ +url | STRING | undefined | The URL of the nextcloud instance. +folder | STRING | undefined | The random string copy-pasted from the share link ([see](#create-file-drop-folder)). +filename | FUNCTION | null | A function `(this.jsPsych) => { return ... }` returning the name of the zip file that will be uploaded. If `null`, the filename will be generated from the actual date. +generate_download_url_on_error | BOOL | false | When the upload failed, should the browser generate an internal URL for the generated ZIP file. This URL may be used by the user for download the ZIP file such that the data can be transferred later. + +### Trial Data +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial: +| Name | Type | Value | +| ---------------- | ----------- | ---------------------------------------- | +| filename | STRING | The name of the uploaded file. | +| error | BOOLEAN | If there was an error in upload or not. | +| url | STRING | In case of an error, the url to download the file. | + +### Example ```js var trial = { type: jsPsychNextcloudFiledropPlugin, @@ -78,15 +94,6 @@ var trial = { }; ``` -Parameter | Type | Default Value | Description -----------|------|---------------|------------ -url | STRING | undefined | The URL of the nextcloud instance. -folder | STRING | undefined | The random string copy-pasted from the share link ([see](#create-file-drop-folder)). -filename | FUNCTION | null | A function `(this.jsPsych) => { return ... }` returning the name of the zip file that will be uploaded. If `null`, the filename will be generated from the actual date. -generate_download_url_on_error | BOOL | false | When the upload failed, should the browser generate an internal URL for the generated ZIP file. This URL may be used by the user for download the ZIP file such that the data can be transferred later. - - - ## Nextcloud docker image To test the plugin locally, a nextcloud instance can be set up using docker. @@ -102,7 +109,7 @@ Create and run the docker container as a daemon and provide the nextcloud insanc ``` sh docker run -d --name nextcloud -p 8081:80 docker.io/library/nextcloud -```` +``` ### 2. Setup Nextcloud @@ -115,7 +122,7 @@ The nextcloud instance need to accept CORS from the webserver. We adapt the example apache configuration from [here](https://github.com/perry-mitchell/webdav-client/issues/116#issuecomment-496032465). Execute the following two lines. -``` sh +```sh RULES=' # Add security and privacy related headers SetEnvIf Origin "http(s)?://(.*)$" AccessControlAllowOrigin=$0 @@ -134,7 +141,7 @@ RewriteRule ^(.*)$ $1 [R=200,L] ' ``` -``` sh +```sh docker exec nextcloud sh -c "echo '$RULES' >> /var/www/html/.htaccess" ``` diff --git a/packages/plugin-pipe/docs/jspsych-pipe.md b/packages/plugin-pipe/docs/jspsych-pipe.md index 1612eefd..9b676c6b 100644 --- a/packages/plugin-pipe/docs/jspsych-pipe.md +++ b/packages/plugin-pipe/docs/jspsych-pipe.md @@ -6,7 +6,7 @@ The plugin enables sending data collected by the experiment to DataPipe, which i ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ----------|------|---------------|------------ | @@ -19,7 +19,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](../overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | @@ -64,14 +64,14 @@ jsPsychPipe.getCondition(experiment_id).then(condition => { // This ID is provided by pipe.jspsych.org. const expID = "ABCDEF123456"; -// Generate a random subject ID. -const subjectID = jsPsych.randomization.randomID(10); +// Generate a random participant ID. +const participantID = jsPsych.randomization.randomID(10); const save_data = { type: jsPsychPipe, action: "save", experiment_id: expID, - filename: `${subjectID}.csv`, + filename: `${participantID}.csv`, data_string: ()=>jsPsych.data.get().csv() }; ``` @@ -82,8 +82,8 @@ const save_data = { // This ID is provided by pipe.jspsych.org. const expID = "ABCDEF123456"; -// Generate a random subject ID. -const subjectID = jsPsych.randomization.randomID(10); +// Generate a random participant ID. +const participantID = jsPsych.randomization.randomID(10); var trial = { type: jsPsychHtmlAudioResponse, @@ -93,7 +93,7 @@ var trial = { recording_duration: 15000, allow_playback: true, on_finish: function(data){ - const filename = `${subjectID}_${jsPsych.getProgress().current_trial_global}_audio.webm`; + const filename = `${participantID}_${jsPsych.getProgress().current_trial_global}_audio.webm`; jsPsychPipe.saveBase64Data(expID, filename, data.response); // optionally, delete the base64 data to save space. store the filename instead. data.response = filename; @@ -101,7 +101,7 @@ var trial = { }; ``` -### Get the condition assignment for a subject. +### Get the condition assignment for a participant. ```javascript // This ID is provided by pipe.jspsych.org. diff --git a/packages/plugin-pipe/examples/jspsych-plugin-pipe-example-1.html b/packages/plugin-pipe/examples/jspsych-plugin-pipe-example-1.html index e35171c8..e4d48d40 100644 --- a/packages/plugin-pipe/examples/jspsych-plugin-pipe-example-1.html +++ b/packages/plugin-pipe/examples/jspsych-plugin-pipe-example-1.html @@ -14,8 +14,8 @@ var jsPsych = initJsPsych({}); - const subject_id = jsPsych.randomization.randomID(10); - jsPsych.data.addProperties({subject_id: subject_id}); + const participant_id = jsPsych.randomization.randomID(10); + jsPsych.data.addProperties({participant_id: participant_id}); const flanker_timeline = { timeline: [{ @@ -42,7 +42,7 @@ type: jsPsychPipe, action: "save", experiment_id: expID, - filename: `${subject_id}.csv`, + filename: `${participant_id}.csv`, data_string: ()=>jsPsych.data.get().csv() }; diff --git a/packages/plugin-pipe/examples/jspsych-plugin-pipe-example-3.html b/packages/plugin-pipe/examples/jspsych-plugin-pipe-example-3.html index 10cd903b..418a4933 100644 --- a/packages/plugin-pipe/examples/jspsych-plugin-pipe-example-3.html +++ b/packages/plugin-pipe/examples/jspsych-plugin-pipe-example-3.html @@ -14,8 +14,8 @@ var jsPsych = initJsPsych({}); - const subject_id = jsPsych.randomization.randomID(10); - jsPsych.data.addProperties({subject_id: subject_id}); + const participant_id = jsPsych.randomization.randomID(10); + jsPsych.data.addProperties({participant_id: participant_id}); var trial = { type: jsPsychHtmlAudioResponse, @@ -25,7 +25,7 @@ recording_duration: 15000, allow_playback: true, on_finish: function(data){ - const filename = `${subject_id}_${jsPsych.getProgress().current_trial_global}_audio.webm`; + const filename = `${participant_id}_${jsPsych.getProgress().current_trial_global}_audio.webm`; jsPsychPipe.saveBase64Data(expID, filename, data.response); // delete the base64 data to save space. store the filename instead. data.response = filename; diff --git a/packages/plugin-pipe/readme.md b/packages/plugin-pipe/readme.md index 96b639da..df745483 100644 --- a/packages/plugin-pipe/readme.md +++ b/packages/plugin-pipe/readme.md @@ -11,7 +11,7 @@ The plugin enables sending data collected by the experiment to DataPipe, which i ### In browser ```js - + ``` ### Via NPM @@ -26,7 +26,7 @@ import jsPsychPipe from '@jspsych-contrib/plugin-pipe'; ## Compatibility -jsPsych v7.0. +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 0.4 of this plugin. ## Documentation diff --git a/packages/plugin-rdk/docs/jspsych-rdk.md b/packages/plugin-rdk/docs/jspsych-rdk.md index f5e88fd7..57d95902 100644 --- a/packages/plugin-rdk/docs/jspsych-rdk.md +++ b/packages/plugin-rdk/docs/jspsych-rdk.md @@ -11,7 +11,7 @@ For optimal performance, fullscreen mode should be manually triggered by the use ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Descripton | | ------------------------ | ---------------- | -------------------- | ---------------------------------------- | @@ -63,7 +63,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. | Name | Type | Value | | ---------------- | ----------- | ---------------------------------------- | diff --git a/packages/plugin-rdk/readme.md b/packages/plugin-rdk/readme.md index 42a7ab81..6f7db427 100644 --- a/packages/plugin-rdk/readme.md +++ b/packages/plugin-rdk/readme.md @@ -24,8 +24,7 @@ import jsPsychRdk from '@jspsych-contrib/plugin-rdk'; ## Compatibility -jsPsych v7.0. - +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.1.0 of this plugin. ## Documentation See [documentation](docs/jspsych-rdk.md) diff --git a/packages/plugin-rok/docs/jspsych-rok.md b/packages/plugin-rok/docs/jspsych-rok.md index 86ab6247..6e3b0eee 100644 --- a/packages/plugin-rok/docs/jspsych-rok.md +++ b/packages/plugin-rok/docs/jspsych-rok.md @@ -10,15 +10,14 @@ We would appreciate it if you cited this paper when you use the plugin: ## Parameters -Parameters can be left unspecified if the default value is acceptable. If more then one aperture is displayed most of the parameters should be specified as array (specified by the array column). -The elements of the array then apply to the corresponding aperture. Features that are not fully implemented yet are marked with an x +Parameters can be left unspecified if the default value is acceptable. If more then one aperture is displayed most of the parameters should be specified as array (specified by the array column). The elements of the array then apply to the corresponding aperture. In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), the parameters for this plugin are as follows: |Parameter|Type|Default Value| Descripton|Array| |---------|----|-------------|-----------|-----| choices|array|[]|The valid keys that the participant can press to indicate a response|must| correct_choice|string|undefined|The correct keys for that trial|can| number_of_apertures|INT|1|Number of apertures. If greater then one, other parameters of trial should be arrays|can| -density_unit_area|INT|null|If this parameter is set, number_of_objects is interpreted as number_of_objects per density_unit_area (in pixels*pixels)" +density_unit_area|INT|null|If this parameter is set, number_of_objects is interpreted as number_of_objects per density_unit_area (in pixels*pixels)"|no| aperture_width|INT|600|The width of the aperture in pixels|can| aperture_height|INT|400|he height of the aperture in pixels|can| aperture_position_left|INT|50|Position of midpoint of aperture in x direction in percentage of window width (50 being middle)|can| @@ -59,7 +58,7 @@ If image are key framed, the keyframes must be loaded as one picture in a frame ## Data Generated -In addition to the default data collected by all plugins, this plugin collects all parameter data described above and the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects all parameter data described above and the following data for each trial. |Name|Type|Value| |----|----|-----| diff --git a/packages/plugin-rok/readme.md b/packages/plugin-rok/readme.md index ea75c5ec..897ee2e5 100644 --- a/packages/plugin-rok/readme.md +++ b/packages/plugin-rok/readme.md @@ -25,7 +25,7 @@ import jsPsychRok from '@jspsych-contrib/plugin-rok'; ## Compatibility -jsPsych v7.0. +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.1.1 of this plugin. ## Documentation diff --git a/packages/plugin-rok/src/index.ts b/packages/plugin-rok/src/index.ts index 47536a0a..663b42c3 100644 --- a/packages/plugin-rok/src/index.ts +++ b/packages/plugin-rok/src/index.ts @@ -649,7 +649,7 @@ class RokPlugin implements JsPsychPlugin { //Variable to start the timer let timerHasStarted = false; - //Initialize object to store the response data. Default values of -1 are used if the trial times out and the subject has not pressed a valid key + //Initialize object to store the response data. Default values of -1 are used if the trial times out and the participant has not pressed a valid key let response = { rt: -1, key: "", @@ -990,9 +990,9 @@ class RokPlugin implements JsPsychPlugin { const startKeyboardListener = () => { //Start the response listener if there are choices for keys if (choices != "NO_KEYS") { - //Create the keyboard listener to listen for subjects' key response + //Create the keyboard listener to listen for participants' key response keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({ - callback_function: after_response, //Function to call once the subject presses a valid key + callback_function: after_response, //Function to call once the participant presses a valid key valid_responses: choices, //The keys that will be considered a valid response and cause the callback function to be called rt_method: "performance", //The type of method to record timing information. persist: false, //If set to false, keyboard listener will only trigger the first time a valid key is pressed. If set to true, it has to be explicitly cancelled by the cancelKeyboardResponse plugin API. @@ -1018,7 +1018,7 @@ class RokPlugin implements JsPsychPlugin { frameRate = (frameRate as number[]).reduce((total, current) => total + current) / numberOfFrames; //Sum up all the elements in the array } else { - frameRate = 0; //Set to zero if the subject presses an answer before a frame is shown (i.e. if frameRate is an empty array) + frameRate = 0; //Set to zero if the participant presses an answer before a frame is shown (i.e. if frameRate is an empty array) } //Cancel the keyboard listener if keyboardListener has been defined @@ -1029,8 +1029,8 @@ class RokPlugin implements JsPsychPlugin { //Place all the data to be saved from this trial in one data object let trial_data = { rt: response.rt, //The response time - key_press: response.key, //The key that the subject pressed - correct: correctOrNot(), //If the subject response was correct + key_press: response.key, //The key that the participant pressed + correct: correctOrNot(), //If the participant response was correct choices: choices, //The set of valid keys correct_choice: correct_choice, //The correct choice trial_duration: trial_duration, //The trial duration @@ -1077,7 +1077,7 @@ class RokPlugin implements JsPsychPlugin { //start animation animateDotMotion(); - //Function to record the first response by the subject + //Function to record the first response by the participant function after_response(info) { //If the response has not been recorded, record it if (response.key == "") { @@ -1145,7 +1145,7 @@ class RokPlugin implements JsPsychPlugin { //frameRequestID saves a long integer that is the ID of this frame request. The ID is then used to terminate the request below. let frameRequestID = window.requestAnimationFrame(animate); - //Start to listen to subject's key responses + //Start to listen to participant's key responses startKeyboardListener(); //Declare a timestamp @@ -1162,8 +1162,8 @@ class RokPlugin implements JsPsychPlugin { //If the timer has not been started and it is set, then start the timer if (!timerHasStarted && trial_duration > 0) { //If the trial duration is set, then set a timer to count down and call the end_trial function when the time is up - //(If the subject did not press a valid keyboard response within the trial duration, then this will end the trial) - timeoutID = window.setTimeout(end_trial, trial_duration); //This timeoutID is then used to cancel the timeout should the subject press a valid key + //(If the participant did not press a valid keyboard response within the trial duration, then this will end the trial) + timeoutID = window.setTimeout(end_trial, trial_duration); //This timeoutID is then used to cancel the timeout should the participant press a valid key //The timer has started, so we set the variable to true so it does not start more timers timerHasStarted = true; } diff --git a/packages/plugin-self-paced-reading/docs/jspsych-self-paced-reading.md b/packages/plugin-self-paced-reading/docs/jspsych-self-paced-reading.md index a27be770..9af335d6 100644 --- a/packages/plugin-self-paced-reading/docs/jspsych-self-paced-reading.md +++ b/packages/plugin-self-paced-reading/docs/jspsych-self-paced-reading.md @@ -4,7 +4,7 @@ jsPsych plugin for self-paced reading experiments. ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of _undefined_ must be specified. Other parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of _undefined_ must be specified. Other parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ------------------- | -------- | ---------------- | ----------------------------------------------- | @@ -34,7 +34,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | -------- | -------- | ---------------------------------------------------------- | diff --git a/packages/plugin-self-paced-reading/src/index.ts b/packages/plugin-self-paced-reading/src/index.ts index 2ab1ac3e..31d1506d 100644 --- a/packages/plugin-self-paced-reading/src/index.ts +++ b/packages/plugin-self-paced-reading/src/index.ts @@ -345,7 +345,7 @@ class SelfPacedReadingPlugin implements JsPsychPlugin { this.jsPsych.finishTrial(trial_data); }; - // function to handle responses by the subject + // function to handle responses by the participant const after_response = (info: { rt: any }) => { // gather/store data rts.push(info.rt); diff --git a/packages/plugin-survey-number/README.md b/packages/plugin-survey-number/README.md index 60c483f9..a1c1b91e 100644 --- a/packages/plugin-survey-number/README.md +++ b/packages/plugin-survey-number/README.md @@ -24,7 +24,7 @@ import jsPsychSurveyNumber from '@jspsych-contrib/plugin-survey-number'; ## Compatibility -jsPsych 8.0.0. For jsPsych 7.0.0, use version 1.0.0. +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-survey-number/docs/survey-number.md b/packages/plugin-survey-number/docs/survey-number.md index 3f0ecad8..1be65719 100644 --- a/packages/plugin-survey-number/docs/survey-number.md +++ b/packages/plugin-survey-number/docs/survey-number.md @@ -8,7 +8,11 @@ In addition to the [parameters available in all plugins](https://jspsych.org/lat | Parameter | Type | Default Value | Description | | ------------------- | ---------------- | ------------------ | ---------------------------------------- | -| | | | | +| questions | array of object | `undefined` | Array of objects of the form `{ prompt: HTML_STRING, placeholder: STRING, rows: INT, columns: INT, required: BOOL, name: STRING }`, where:
`prompt`: Question prompt.
`placeholder`: Placeholder text to put in the response text box.
`rows`: Number of rows for the response text box.
`columns`: Number of columns for the response text box.
`required`: If the participant must give a response to continue in the trial.
`name`: Name of the question in the trial data. If not specified, questions are named `"Q0"`, `"Q1"`, etc... | +| randomize_question_order | boolean | `false` | If true, the order of questions in the `questions` array are randomized. | +| preamble | HTML string | `null` | HTML-formatted string that is displayed above all the questions. | +| button_label | string | `"Continue"` | Label of the button to submit responses. | +| autocomplete | boolean | `false` | If true, browser auto-complete or auto-fill will be enabled. | ## Data Generated @@ -16,7 +20,8 @@ In addition to the [default data collected by all plugins](https://jspsych.org/l | Name | Type | Value | | --------- | ------- | ---------------------------------------- | -| | | | +| rt | integer | The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. | +| response | object | An object containing the string of the response given by the participant. | ## Install @@ -44,10 +49,15 @@ import SurveyNumber from '@jspsych-contrib/plugin-survey-number'; ## Examples -### Title of Example +### A trial to ask for age with a slider ```javascript var trial = { - type: jsPsychSurveyNumber + type: jsPsychSurveyNumber, + questions: [{ + prompt: 'How old are you?', + name: 'age', + required: true, + }] } ``` \ No newline at end of file diff --git a/packages/plugin-survey-slider/README.md b/packages/plugin-survey-slider/README.md index a338187b..d1767438 100644 --- a/packages/plugin-survey-slider/README.md +++ b/packages/plugin-survey-slider/README.md @@ -27,7 +27,7 @@ import jsPsychSurveySlider from '@jspsych-contrib/plugin-survey-slider'; ## Compatibility -jsPsych 8.0.0. For using jsPsych v7.0, use version 1.0.0. +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-survey-slider/docs/survey-slider.md b/packages/plugin-survey-slider/docs/survey-slider.md index 77ba6b36..10ec6b33 100644 --- a/packages/plugin-survey-slider/docs/survey-slider.md +++ b/packages/plugin-survey-slider/docs/survey-slider.md @@ -4,19 +4,27 @@ Add several analogue scales on the same page for use in questionnaires ## Parameters -In addition to the [parameters available in all plugins](https://jspsych.org/latest/overview/plugins.md#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ------------------- | ---------------- | ------------------ | ---------------------------------------- | -| | | | | +| questions | array of object | `undefined` | Array of objects of the form `{ stimulus: HTML_STRING, prompt: STRING, labels: STRING[], ticks: STRING[], name: STRING, min: INT, max: INT, slider_start: INT, step: INT }`, where:
`stimulus`: The HTML string to be displayed.
`prompt`: Content to be displayed below the stimulus and above the slider.
`labels`: Labels to appear to the left of each slider, one in line with the top row ticks and one in line with the bottom.
`ticks`: Array containing ticks that will be displayed in equidistant locations along the slider.
`name`: Name of the data value associated with this question.
`min`: Minimum value of the slider.
`max`: Maximum value of the slider.
`slider_start`: Starting value of the slider.
`step`: The value between each movement of the slider. | +| randomize_question_order | boolean | `false` | If true, the order of questions in the `questions` array are randomized. | +| preamble | HTML string | `null` | HTML-formatted string that is displayed above all the questions. | +| button_label | string | `"Continue"` | Label of the button to submit responses. | +| autocomplete | boolean | `false` | If true, browser auto-complete or auto-fill will be enabled. | +| require_movement | boolean | `false` | If true, the participant will need to input a value into the slider before moving on. | +| slider_width | integer | 500 | Width of the slider, in pixels. | ## Data Generated -In addition to the [default data collected by all plugins](https://jspsych.org/latest/overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | -| | | | +| rt | integer | The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. | +| response | string | An JSON object stringified, containing the responses given by the participant. | +| question_order | string | The order in which the questions were presented. | ## Install diff --git a/packages/plugin-survey-slider/src/index.ts b/packages/plugin-survey-slider/src/index.ts index 9836a202..abd60bbe 100644 --- a/packages/plugin-survey-slider/src/index.ts +++ b/packages/plugin-survey-slider/src/index.ts @@ -6,6 +6,7 @@ const info = { name: "survey-slider", version: "2.0.0", parameters: { + /** Questions that will be displayed to the participant. */ questions: { type: ParameterType.COMPLEX, array: true, diff --git a/packages/plugin-video-several-keyboard-responses/README.md b/packages/plugin-video-several-keyboard-responses/README.md index 95eb8135..90888227 100644 --- a/packages/plugin-video-several-keyboard-responses/README.md +++ b/packages/plugin-video-several-keyboard-responses/README.md @@ -24,7 +24,7 @@ import jsPsychVideoSeveralKeyboardResponses from '@jspsych-contrib/plugin-video- ## Compatibility -jsPsych v7.3.4 +jsPsych v8.0. For compatibility with jsPsych v7.3+, use version 2.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-video-several-keyboard-responses/docs/jspsych-video-several-keyboard-responses.md b/packages/plugin-video-several-keyboard-responses/docs/jspsych-video-several-keyboard-responses.md index 33e91492..2fadd6b4 100644 --- a/packages/plugin-video-several-keyboard-responses/docs/jspsych-video-several-keyboard-responses.md +++ b/packages/plugin-video-several-keyboard-responses/docs/jspsych-video-several-keyboard-responses.md @@ -4,19 +4,22 @@ Based on [video-keyboard-response](https://github.com/jspsych/jsPsych/tree/main/ ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins) and [video-keyboard-response](https://github.com/jspsych/jsPsych/blob/main/docs/plugins/video-keyboard-response.md) plugin, this plugin accepts the following parameters. Parameters with a default value of _undefined_ must be specified. Other parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins) and [video-keyboard-response](https://github.com/jspsych/jsPsych/blob/main/docs/plugins/video-keyboard-response.md) plugin, this plugin accepts the following parameters. Parameters with a default value of _undefined_ must be specified. Other parameters can be left unspecified if the default value is acceptable. -| Parameter | Type | Default Value | Description | -| -------------------------- | ---- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| Parameter | Type | Default Value | Description | +| -------------------------- | ---- | ------------- | -------------------------------- | | multiple_responses_allowed | bool | true | If true, multiple responses are recorded. If false, only the first response will be recorded, thus behaving as video-keyboard-response plugin. | ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | ---------- | -------- | ---------------------------------------------------------------- | -| video_time | number[] | Array of playback positions of video when response was given (s) | +| rt | number[] | An array of the response time in milliseconds for each key press from the participant. The time is measured from when the stimulus first began playing until the participant's response. | +| stimulus | string | The stimulus displayed to the participant. | +| response | string[] | An array of the keys that the participant pressed in order. | +| video_time | number[] | An array of playback positions of video when response(s) was given. | ## Example diff --git a/packages/plugin-video-several-keyboard-responses/src/index.ts b/packages/plugin-video-several-keyboard-responses/src/index.ts index 4360b64a..30d2ad40 100644 --- a/packages/plugin-video-several-keyboard-responses/src/index.ts +++ b/packages/plugin-video-several-keyboard-responses/src/index.ts @@ -11,7 +11,7 @@ const info = { default: undefined, array: true, }, - /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */ + /** Array containing the key(s) the participant is allowed to press to respond to the stimulus. */ choices: { type: ParameterType.KEYS, pretty_name: "Choices", @@ -41,7 +41,7 @@ const info = { pretty_name: "Autoplay", default: true, }, - /** If true, the subject will be able to pause the video or move the playback to any point in the video. */ + /** If true, the participant will be able to pause the video or move the playback to any point in the video. */ controls: { type: ParameterType.BOOL, pretty_name: "Controls", @@ -77,7 +77,7 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** If true, the trial will end when subject makes a response. */ + /** If true, the trial will end when participant makes a response. */ response_ends_trial: { type: ParameterType.BOOL, pretty_name: "Response ends trial", @@ -107,7 +107,7 @@ const info = { stimulus: { type: ParameterType.STRING, }, - /** An array of the keys that the subject pressed in order. */ + /** An array of the keys that the participant pressed in order. */ response: { type: ParameterType.STRING, array: true, @@ -304,7 +304,7 @@ class VideoSeveralKeyboardResponsesPlugin implements JsPsychPlugin { this.jsPsych.finishTrial(trial_data); }; - // function to handle responses by the subject + // function to handle responses by the participant var after_response = (info) => { // after a valid response, the stimulus will have the CSS class 'responded' // which can be used to provide visual feedback that a response was recorded diff --git a/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md b/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md index 469a2410..7041ce00 100644 --- a/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md +++ b/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md @@ -22,13 +22,13 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org | image_size | array | `[100, 100]` | Array specifying the width and height of the images to show. The occluding rectangle will have a width equal to the width of image_size. | | initial_direction | string | "left" | Which direction the stimulus should move first (subsequent directions will alternate). Choices are "left" or "right". | | occlude_center | boolean | true | If true, display a rectangle in the center of the screen that is just wide enough to occlude the image completely as it passes behind. | -| choices | array of strings | `jsPsych.ALL_KEYS` | This array contains the key(s) that the subject is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. The default value of `jsPsych.ALL_KEYS` means that all keys will be accepted as valid responses. Specifying `jsPsych.NO_KEYS` will mean that no responses are allowed. | +| choices | array of strings | `jsPsych.ALL_KEYS` | This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/) for more examples. Any key presses that are not listed in the array will be ignored. The default value of `jsPsych.ALL_KEYS` means that all keys will be accepted as valid responses. Specifying `jsPsych.NO_KEYS` will mean that no responses are allowed. | | cycle_duration | numeric | 1000 | How long it takes for a stimulus in the sequence to make a complete cycle (move to the edge and back to the center) in milliseconds. | | pre_movement_duration | numeric | 500 | How long to wait before the stimuli starts moving from behind the center rectangle. | ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ----------- | ---------------------------------------- | diff --git a/packages/plugin-vsl-animate-occlusion/readme.md b/packages/plugin-vsl-animate-occlusion/readme.md index 8f1b82c4..bcd1e03e 100644 --- a/packages/plugin-vsl-animate-occlusion/readme.md +++ b/packages/plugin-vsl-animate-occlusion/readme.md @@ -27,7 +27,7 @@ import jsPsychVslAnimateOcclusion from '@jspsych-contrib/plugin-vsl-animate-occl ## Compatibility -jsPsych v7.0. +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/packages/plugin-vsl-animate-occlusion/src/index.ts b/packages/plugin-vsl-animate-occlusion/src/index.ts index f1ade8e9..be751d88 100644 --- a/packages/plugin-vsl-animate-occlusion/src/index.ts +++ b/packages/plugin-vsl-animate-occlusion/src/index.ts @@ -12,7 +12,7 @@ const info = { default: undefined, array: true, }, - /** Array containing the key(s) that the subject is allowed to press in order to respond to the stimulus. */ + /** Array containing the key(s) that the participant is allowed to press in order to respond to the stimulus. */ choices: { type: ParameterType.KEYS, pretty_name: "Choices", diff --git a/packages/plugin-vsl-grid-scene/docs/jspsych-vsl-grid-scene.md b/packages/plugin-vsl-grid-scene/docs/jspsych-vsl-grid-scene.md index e11e507e..f1acbb9c 100644 --- a/packages/plugin-vsl-grid-scene/docs/jspsych-vsl-grid-scene.md +++ b/packages/plugin-vsl-grid-scene/docs/jspsych-vsl-grid-scene.md @@ -6,7 +6,7 @@ Fiser, J., & Aslin, R. N. (2001). Unsupervised statistical learning of higher-or ## Parameters -In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Other parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Other parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | -------------- | ------- | ------------- | ---------------------------------------- | @@ -16,7 +16,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org ## Data Generated -In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | -------- | ----------- | ---------------------------------------- | diff --git a/packages/plugin-vsl-grid-scene/readme.md b/packages/plugin-vsl-grid-scene/readme.md index 9ddb4b48..cfe311a5 100644 --- a/packages/plugin-vsl-grid-scene/readme.md +++ b/packages/plugin-vsl-grid-scene/readme.md @@ -26,7 +26,7 @@ import jsPsychVslGridScene from '@jspsych-contrib/plugin-vsl-grid-scene'; ## Compatibility -jsPsych v7.0. +jsPsych v8.0. For compatibility with jsPsych v7.0, use version 1.0.0 of this plugin. ## Documentation diff --git a/templates/plugin-template-js/docs/docs-template.md b/templates/plugin-template-js/docs/docs-template.md index 7183c9e3..ebce2809 100644 --- a/templates/plugin-template-js/docs/docs-template.md +++ b/templates/plugin-template-js/docs/docs-template.md @@ -4,7 +4,7 @@ ## Parameters -In addition to the [parameters available in all plugins](https://jspsych.org/latest/overview/plugins.md#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ------------------- | ---------------- | ------------------ | ---------------------------------------- | @@ -12,7 +12,7 @@ In addition to the [parameters available in all plugins](https://jspsych.org/lat ## Data Generated -In addition to the [default data collected by all plugins](https://jspsych.org/latest/overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | diff --git a/templates/plugin-template-ts/docs/docs-template.md b/templates/plugin-template-ts/docs/docs-template.md index 7183c9e3..ebce2809 100644 --- a/templates/plugin-template-ts/docs/docs-template.md +++ b/templates/plugin-template-ts/docs/docs-template.md @@ -4,7 +4,7 @@ ## Parameters -In addition to the [parameters available in all plugins](https://jspsych.org/latest/overview/plugins.md#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. +In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ------------------- | ---------------- | ------------------ | ---------------------------------------- | @@ -12,7 +12,7 @@ In addition to the [parameters available in all plugins](https://jspsych.org/lat ## Data Generated -In addition to the [default data collected by all plugins](https://jspsych.org/latest/overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. +In addition to the [default data collected by all plugins](https://www.jspsych.org/latest/overview/plugins/#data-collected-by-all-plugins), this plugin collects the following data for each trial. | Name | Type | Value | | --------- | ------- | ---------------------------------------- | From 1af38c487c22541cbf52b69311dbdd114db14321 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Sat, 19 Oct 2024 00:28:00 -0400 Subject: [PATCH 28/30] clarify nested data types --- packages/plugin-copying-task/src/index.js | 20 ++++++++++++++++--- packages/plugin-corsi-blocks/src/index.ts | 15 +++++++++++++- packages/plugin-gamepad/src/index.ts | 1 + .../plugin-html-keyboard-slider/src/index.ts | 2 +- packages/plugin-html-vas-response/index.js | 16 ++++++++++++--- packages/plugin-survey-slider/src/index.ts | 2 -- .../docs/jspsych-vsl-animate-occlusion.md | 2 +- .../plugin-vsl-animate-occlusion/src/index.ts | 20 +++++++++++++++++-- 8 files changed, 65 insertions(+), 13 deletions(-) diff --git a/packages/plugin-copying-task/src/index.js b/packages/plugin-copying-task/src/index.js index 74af4696..1b8cfcf4 100644 --- a/packages/plugin-copying-task/src/index.js +++ b/packages/plugin-copying-task/src/index.js @@ -164,19 +164,23 @@ var jsPsychCopyingTask = (function (jspsych) { }, /** The contents of the grids as the trial ends. */ grid_contents: { - type: jspsych.ParameterType.COMPLEX, //TODO: specify structure of model/workspace/resource grid contents + type: jspsych.ParameterType.COMPLEX, nested: { + // all are arrays of arrays of strings /** The contents of the model grid the participant was to copy. */ model: { type: jspsych.ParameterType.COMPLEX, + array: true, }, /** The contents of the workspace grid the participant was to copy the model grid to. */ workspace: { type: jspsych.ParameterType.COMPLEX, + array: true, }, /** The contents of the resource grid where participants were given images to drag to the workspace. */ resource: { type: jspsych.ParameterType.COMPLEX, + array: true, }, }, }, @@ -184,7 +188,7 @@ var jsPsychCopyingTask = (function (jspsych) { trial_events: { type: jspsych.ParameterType.COMPLEX, array: true, - parameters: { + nested: { /** The type of event the interaction was, split into if the participant successfully or unsuccessfully * interacted with the resource grid image, along with if the item was placed correctly or not. */ event: { @@ -201,7 +205,17 @@ var jsPsychCopyingTask = (function (jspsych) { }, /** The location on the resource grid that the participant interacted with. */ grid_coords: { - type: jspsych.ParameterType.COMPLEX, //TODO: add "row" and "column" demarkations + type: jspsych.ParameterType.COMPLEX, + nested: { + /** The row of the resource grid the participant interacted with. */ + row: { + type: jspsych.ParameterType.INT, + }, + /** The column of the resource grid the participant interacted with. */ + column: { + type: jspsych.ParameterType.INT, + }, + }, }, /** The timestamp of when the interaction occured, in milliseconds measured from when the stimulus appeared. */ timestamp: { diff --git a/packages/plugin-corsi-blocks/src/index.ts b/packages/plugin-corsi-blocks/src/index.ts index 3af05070..7e2b3f52 100644 --- a/packages/plugin-corsi-blocks/src/index.ts +++ b/packages/plugin-corsi-blocks/src/index.ts @@ -143,25 +143,38 @@ const info = { }, }, data: { + /** The sequence of block indicies that were displayed. */ sequence: { type: ParameterType.INT, array: true, }, + /** The sequence of blocks that were selected by the participant. */ response: { type: ParameterType.INT, array: true, }, + /** The time, in milliseconds, that the participant took to respond to each block. + * These times are cumulative, measured from the onset of the display. */ rt: { type: ParameterType.INT, array: true, }, + /** The x and y coordinates of each block that was displayed. */ blocks: { type: ParameterType.COMPLEX, array: true, + nested: { + x: { + type: ParameterType.INT, + }, + y: { + type: ParameterType.INT, + }, + }, }, + /** Whether the participant's response was correct. */ correct: { type: ParameterType.BOOL, - default: null, }, }, }; diff --git a/packages/plugin-gamepad/src/index.ts b/packages/plugin-gamepad/src/index.ts index 03abc55a..e65a79e3 100644 --- a/packages/plugin-gamepad/src/index.ts +++ b/packages/plugin-gamepad/src/index.ts @@ -89,6 +89,7 @@ const info = { /** The gamepad inputs recorded during the trial. */ input: { type: ParameterType.COMPLEX, + array: true, }, }, }; diff --git a/packages/plugin-html-keyboard-slider/src/index.ts b/packages/plugin-html-keyboard-slider/src/index.ts index f7129d55..4a19e20c 100644 --- a/packages/plugin-html-keyboard-slider/src/index.ts +++ b/packages/plugin-html-keyboard-slider/src/index.ts @@ -14,7 +14,7 @@ const info = { * Slider minimum - Note Ints here can also be floats without issue */ min: { - type: ParameterType.INT, // BOOL, STRING, INT, FLOAT, FUNCTION, KEY, KEYS, SELECT, HTML_STRING, IMAGE, AUDIO, VIDEO, OBJECT, COMPLEX + type: ParameterType.INT, default: 0, }, /** diff --git a/packages/plugin-html-vas-response/index.js b/packages/plugin-html-vas-response/index.js index 5678ccc8..0cb1fb4c 100644 --- a/packages/plugin-html-vas-response/index.js +++ b/packages/plugin-html-vas-response/index.js @@ -136,12 +136,22 @@ var jsPsychHtmlVasResponse = (function (jspsych) { type: jspsych.ParameterType.STRING, }, /** - * A record of the participant's clicks on the scale. Each element in the array is an object with properties `time` - * (the time of the click, in milliseconds since the trial began) and `location` - * (the location of the click on the VAS, from 0 to 1). + * A record of the participant's clicks on the scale. Each element in the array is an object + * with properties `time` and `location`. */ clicks: { type: jspsych.ParameterType.COMPLEX, + array: true, + nested: { + /** The time of the click, in milliseconds since the trial began. */ + time: { + type: jspsych.ParameterType.INT, + }, + /** The location of the click on the VAS, from 0 to 1. */ + location: { + type: jspsych.ParameterType.FLOAT, + }, + }, }, }, }; diff --git a/packages/plugin-survey-slider/src/index.ts b/packages/plugin-survey-slider/src/index.ts index abd60bbe..2025fc9c 100644 --- a/packages/plugin-survey-slider/src/index.ts +++ b/packages/plugin-survey-slider/src/index.ts @@ -1,7 +1,5 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; -// BOOL, STRING, INT, FLOAT, FUNCTION, KEY, KEYS, SELECT, HTML_STRING, IMAGE, AUDIO, VIDEO, OBJECT, COMPLEX - const info = { name: "survey-slider", version: "2.0.0", diff --git a/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md b/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md index 7041ce00..dd0ce984 100644 --- a/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md +++ b/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md @@ -32,7 +32,7 @@ In addition to the [default data collected by all plugins](https://www.jspsych.o | Name | Type | Value | | --------- | ----------- | ---------------------------------------- | -| stimulus | array | Array where each element is a stimulus from the sequence, in the order that they were shown. This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. | +| stimuli | array | Array where each element is a stimulus from the sequence, in the order that they were shown. This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. | | response | array | Array containing all response information. Each element in the array is an object representing each valid response. Each response item has three properties: `key` the key that was pressed, `stimulus` the index of the stimulus that was displayed when the response was made, and `rt` the response time measured since the start of the sequence. This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. | ## Examples diff --git a/packages/plugin-vsl-animate-occlusion/src/index.ts b/packages/plugin-vsl-animate-occlusion/src/index.ts index be751d88..1313623b 100644 --- a/packages/plugin-vsl-animate-occlusion/src/index.ts +++ b/packages/plugin-vsl-animate-occlusion/src/index.ts @@ -66,11 +66,27 @@ const info = { * when data is saved using the `.json()` or `.csv()` functions. */ response: { type: ParameterType.COMPLEX, + array: true, + nested: { + /** The key that was pressed. */ + key: { + type: ParameterType.STRING, + }, + /** The index of the stimulus that was displayed when the response was made. */ + stimulus: { + type: ParameterType.INT, + }, + /** The response time measured since the start of the sequence. */ + rt: { + type: ParameterType.INT, + }, + }, }, /** Array where each element is a stimulus from the sequence, in the order that they were shown. * This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. */ - stimulus: { - type: ParameterType.COMPLEX, + stimuli: { + type: ParameterType.STRING, + array: true, }, }, }; From 1a7604b7331df666e954156724dc29228b37ffe7 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Sat, 19 Oct 2024 20:50:00 -0400 Subject: [PATCH 29/30] add changeset --- .changeset/thick-llamas-greet.md | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .changeset/thick-llamas-greet.md diff --git a/.changeset/thick-llamas-greet.md b/.changeset/thick-llamas-greet.md new file mode 100644 index 00000000..3419be52 --- /dev/null +++ b/.changeset/thick-llamas-greet.md @@ -0,0 +1,33 @@ +--- +"@jspsych-contrib/plugin-video-several-keyboard-responses": major +"@jspsych-contrib/plugin-image-array-keyboard-response": major +"@jspsych-contrib/plugin-html-keyboard-response-raf": major +"@jspsych-contrib/plugin-libet-intentional-binding": major +"@jspsych-contrib/extension-mediapipe-face-mesh": major +"@jspsych-contrib/extension-touchscreen-buttons": major +"@jspsych-contrib/plugin-vsl-animate-occlusion": major +"@jspsych-contrib/plugin-audio-multi-response": major +"@jspsych-contrib/plugin-audio-swipe-response": major +"@jspsych-contrib/plugin-html-keyboard-slider": major +"@jspsych-contrib/plugin-image-multi-response": major +"@jspsych-contrib/plugin-image-swipe-response": major +"@jspsych-contrib/plugin-html-multi-response": major +"@jspsych-contrib/plugin-html-swipe-response": major +"@jspsych-contrib/plugin-nextcloud-filedrop": major +"@jspsych-contrib/plugin-self-paced-reading": major +"@jspsych-contrib/plugin-html-vas-response": major +"@jspsych-contrib/extension-device-motion": major +"@jspsych-contrib/plugin-vsl-grid-scene": major +"@jspsych-contrib/plugin-survey-number": major +"@jspsych-contrib/plugin-survey-slider": major +"@jspsych-contrib/plugin-copying-task": major +"@jspsych-contrib/plugin-corsi-blocks": major +"@jspsych-contrib/plugin-html-choice": major +"@jspsych-contrib/plugin-gamepad": major +"@jspsych-contrib/plugin-ios": major +"@jspsych-contrib/plugin-rdk": major +"@jspsych-contrib/plugin-rok": major +"@jspsych-contrib/plugin-pipe": minor +--- + +Plugin updated to use jsPsych v8, with data now properly typed, proper audio integration, and unnecessary timeout/display clears removed. To use v7, check the README.md file for which version is compatible. From b250c20a97bdfcdcaf89113f968b5455d0924555 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Sat, 19 Oct 2024 20:51:53 -0400 Subject: [PATCH 30/30] remove extensions from the changeset --- .changeset/thick-llamas-greet.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/.changeset/thick-llamas-greet.md b/.changeset/thick-llamas-greet.md index 3419be52..89933a17 100644 --- a/.changeset/thick-llamas-greet.md +++ b/.changeset/thick-llamas-greet.md @@ -3,8 +3,6 @@ "@jspsych-contrib/plugin-image-array-keyboard-response": major "@jspsych-contrib/plugin-html-keyboard-response-raf": major "@jspsych-contrib/plugin-libet-intentional-binding": major -"@jspsych-contrib/extension-mediapipe-face-mesh": major -"@jspsych-contrib/extension-touchscreen-buttons": major "@jspsych-contrib/plugin-vsl-animate-occlusion": major "@jspsych-contrib/plugin-audio-multi-response": major "@jspsych-contrib/plugin-audio-swipe-response": major @@ -16,7 +14,6 @@ "@jspsych-contrib/plugin-nextcloud-filedrop": major "@jspsych-contrib/plugin-self-paced-reading": major "@jspsych-contrib/plugin-html-vas-response": major -"@jspsych-contrib/extension-device-motion": major "@jspsych-contrib/plugin-vsl-grid-scene": major "@jspsych-contrib/plugin-survey-number": major "@jspsych-contrib/plugin-survey-slider": major