diff --git a/addons/rose/addon/components/rose/form/checkbox/group/index.hbs b/addons/rose/addon/components/rose/form/checkbox/group/index.hbs
new file mode 100644
index 000000000..795df326d
--- /dev/null
+++ b/addons/rose/addon/components/rose/form/checkbox/group/index.hbs
@@ -0,0 +1,12 @@
+{{#each @items as |item|}}
+ {{yield (hash
+ item=item
+ checkbox=(component 'rose/form/checkbox'
+ name=@name
+ disabled=@disabled
+ inline=@inline
+ checked=(includes item @selectedItems)
+ onChange=(fn this.toggleItem item)
+ )
+ )}}
+{{/each}}
diff --git a/addons/rose/addon/components/rose/form/checkbox/group/index.js b/addons/rose/addon/components/rose/form/checkbox/group/index.js
new file mode 100644
index 000000000..bd240645a
--- /dev/null
+++ b/addons/rose/addon/components/rose/form/checkbox/group/index.js
@@ -0,0 +1,37 @@
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { action } from '@ember/object';
+
+/**
+ * A checkbox group represents an array of arbitrary items, which differs from
+ * single checkboxes which represent boolean values. When checkboxes within a
+ * checkbox are toggled, their associated item is toggled within the group's
+ * array value.
+ *
+ * The term "item" is used to disambiguate it from "value", which has an
+ * existing meaning in the context of form fields. However, items
+ * are just arbitrary values.
+ */
+export default class RoseFormCheckboxGroupComponent extends Component {
+ // =actions
+
+ /**
+ * Returns a new copy of the @selectedItems array where the given item is:
+ * - removed from the array, if it was already present
+ * - or added to the array, if it was not already present
+ */
+ @action
+ toggleItem(item) {
+ const selectedItems = this.args.selectedItems || [];
+ const currentItems = [...selectedItems];
+
+ if (currentItems.includes(item)) {
+ const i = currentItems.indexOf(item);
+ currentItems.splice(i, 1);
+ } else {
+ currentItems.push(item);
+ }
+
+ if (this.args.onChange) this.args.onChange(currentItems);
+ }
+}
diff --git a/addons/rose/addon/components/rose/form/checkbox/group/index.stories.mdx b/addons/rose/addon/components/rose/form/checkbox/group/index.stories.mdx
new file mode 100644
index 000000000..e5a87308d
--- /dev/null
+++ b/addons/rose/addon/components/rose/form/checkbox/group/index.stories.mdx
@@ -0,0 +1,54 @@
+import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
+import { hbs } from 'ember-cli-htmlbars';
+import { action } from '@storybook/addon-actions';
+import { text, boolean, select, object } from '@storybook/addon-knobs';
+
+
+
+# Form checkboxfield group
+
+Renders a form checkboxfield group.
+
+```htmlbars
+
+
+
+```
+
+ {{
+ template: hbs`
+
+
+
+ `,
+ context: {
+ inline: boolean('inline', true),
+ disabled: boolean('disabled', false),
+ items: object('items', [
+ { id: 1, name: 'Foo' },
+ { id: 2, name: 'Bar' },
+ { id: 3, name: 'Baz' },
+ ]),
+ selectedItems: object('selectedItems', []),
+ onChange: action('changed'),
+ }
+ }}
+
diff --git a/addons/rose/app/components/rose/form/checkbox/group.js b/addons/rose/app/components/rose/form/checkbox/group.js
new file mode 100644
index 000000000..4986bf171
--- /dev/null
+++ b/addons/rose/app/components/rose/form/checkbox/group.js
@@ -0,0 +1 @@
+export { default } from 'rose/components/rose/form/checkbox/group';
diff --git a/addons/rose/package.json b/addons/rose/package.json
index 8d9f8b7d8..bc048b236 100644
--- a/addons/rose/package.json
+++ b/addons/rose/package.json
@@ -64,6 +64,7 @@
"ember-cli-sass": "^10.0.1",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
+ "ember-composable-helpers": "^4.5.0",
"ember-disable-prototype-extensions": "^1.1.3",
"ember-export-application-global": "^2.0.1",
"ember-inline-svg": "^1.0.0",
diff --git a/addons/rose/tests/dummy/app/controllers/index.js b/addons/rose/tests/dummy/app/controllers/index.js
index 45faa7e5a..08fa2b4f1 100644
--- a/addons/rose/tests/dummy/app/controllers/index.js
+++ b/addons/rose/tests/dummy/app/controllers/index.js
@@ -1,12 +1,28 @@
import Controller from '@ember/controller';
+import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
+const possibleItems = [
+ { id: 1, name: 'foo' },
+ { id: 2, name: 'bar' },
+ { id: 3, name: 'baz' },
+];
+
export default class IndexController extends Controller {
- color = 'green';
+ // =attributes
+
+ @tracked items = [...possibleItems];
+ @tracked selectedItems = [possibleItems[2]];
+
+ // =actions
@action
- actionHandler(/*value*/) {
- // eslint-disable-next-line no-console
- //console.log('action handled');
+ checkboxGroupChanged(selected) {
+ this.selectedItems = [...selected];
+ }
+
+ @action
+ clearSelected() {
+ this.selectedItems = [];
}
}
diff --git a/addons/rose/tests/dummy/app/templates/index.hbs b/addons/rose/tests/dummy/app/templates/index.hbs
index ed8345c31..812e1ef45 100644
--- a/addons/rose/tests/dummy/app/templates/index.hbs
+++ b/addons/rose/tests/dummy/app/templates/index.hbs
@@ -1,3 +1,28 @@
+
Checkbox Group
+
+
+
+
+
+ Items selected:
+ {{#each this.selectedItems as |selected|}}
+ {{selected.id}},
+ {{/each}}
+
+
+
+ Clear Selected Items
+
+
+
+
KeyValue Dropdown
+
+
+ `);
+ assert.equal(findAll('input').length, 3);
+ });
+
+ test('it checks checkboxes for items present in a selectedItems array', async function (assert) {
+ assert.expect(1);
+ this.items = items;
+ this.selectedItems = selectedItems;
+ await render(hbs`
+
+
+
+ `);
+ assert.equal(findAll(':checked').length, 1);
+ });
+
+ test('it fires onChange when items are checked, passing an array of selected items', async function (assert) {
+ assert.expect(2);
+ this.items = items;
+ this.selectedItems = selectedItems;
+ this.onChange = (newlySelectedItems) => {
+ assert.equal(selectedItems.length, 1);
+ assert.equal(newlySelectedItems.length, 2);
+ };
+ await render(hbs`
+
+
+
+ `);
+ await click('.rose-form-checkbox:first-child input');
+ });
+
+ test('it fires onChange when items are unchecked, passing an array of selected items', async function (assert) {
+ assert.expect(2);
+ this.items = items;
+ this.selectedItems = selectedItems;
+ this.onChange = (newlySelectedItems) => {
+ assert.equal(selectedItems.length, 1);
+ assert.equal(newlySelectedItems.length, 0);
+ };
+ await render(hbs`
+
+
+
+ `);
+ await click('.rose-form-checkbox:last-child input');
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 9e8fd65eb..8fc69c860 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -78,6 +78,27 @@
semver "^6.3.0"
source-map "^0.5.0"
+"@babel/core@^7.0.0", "@babel/core@^7.15.8":
+ version "7.15.8"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10"
+ integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==
+ dependencies:
+ "@babel/code-frame" "^7.15.8"
+ "@babel/generator" "^7.15.8"
+ "@babel/helper-compilation-targets" "^7.15.4"
+ "@babel/helper-module-transforms" "^7.15.8"
+ "@babel/helpers" "^7.15.4"
+ "@babel/parser" "^7.15.8"
+ "@babel/template" "^7.15.4"
+ "@babel/traverse" "^7.15.4"
+ "@babel/types" "^7.15.6"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.1.2"
+ semver "^6.3.0"
+ source-map "^0.5.0"
+
"@babel/core@^7.14.8", "@babel/core@^7.15.5":
version "7.15.5"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.5.tgz#f8ed9ace730722544609f90c9bb49162dc3bf5b9"
@@ -99,27 +120,6 @@
semver "^6.3.0"
source-map "^0.5.0"
-"@babel/core@^7.15.8":
- version "7.15.8"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10"
- integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==
- dependencies:
- "@babel/code-frame" "^7.15.8"
- "@babel/generator" "^7.15.8"
- "@babel/helper-compilation-targets" "^7.15.4"
- "@babel/helper-module-transforms" "^7.15.8"
- "@babel/helpers" "^7.15.4"
- "@babel/parser" "^7.15.8"
- "@babel/template" "^7.15.4"
- "@babel/traverse" "^7.15.4"
- "@babel/types" "^7.15.6"
- convert-source-map "^1.7.0"
- debug "^4.1.0"
- gensync "^1.0.0-beta.2"
- json5 "^2.1.2"
- semver "^6.3.0"
- source-map "^0.5.0"
-
"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.15.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15"
@@ -6685,6 +6685,25 @@ broccoli-funnel-reducer@^1.0.0:
resolved "https://registry.yarnpkg.com/broccoli-funnel-reducer/-/broccoli-funnel-reducer-1.0.0.tgz#11365b2a785aec9b17972a36df87eef24c5cc0ea"
integrity sha1-ETZbKnha7JsXlyo234fu8kxcwOo=
+broccoli-funnel@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/broccoli-funnel/-/broccoli-funnel-2.0.1.tgz#6823c73b675ef78fffa7ab800f083e768b51d449"
+ integrity sha512-C8Lnp9TVsSSiZMGEF16C0dCiNg2oJqUKwuZ1K4kVC6qRPG/2Cj/rtB5kRCC9qEbwqhX71bDbfHROx0L3J7zXQg==
+ dependencies:
+ array-equal "^1.0.0"
+ blank-object "^1.0.1"
+ broccoli-plugin "^1.3.0"
+ debug "^2.2.0"
+ fast-ordered-set "^1.0.0"
+ fs-tree-diff "^0.5.3"
+ heimdalljs "^0.2.0"
+ minimatch "^3.0.0"
+ mkdirp "^0.5.0"
+ path-posix "^1.0.0"
+ rimraf "^2.4.3"
+ symlink-or-copy "^1.0.0"
+ walk-sync "^0.3.1"
+
broccoli-funnel@^1.0.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/broccoli-funnel/-/broccoli-funnel-1.2.0.tgz#cddc3afc5ff1685a8023488fff74ce6fb5a51296"
@@ -7186,14 +7205,14 @@ browserify-zlib@^0.2.0:
pako "~1.0.5"
browserslist@4.14.2, browserslist@^3.2.6, browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.5, browserslist@^4.16.6, browserslist@^4.16.7, browserslist@^4.17.3:
- version "4.17.4"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.4.tgz#72e2508af2a403aec0a49847ef31bd823c57ead4"
- integrity sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ==
+ version "4.17.5"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.5.tgz#c827bbe172a4c22b123f5e337533ceebadfdd559"
+ integrity sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==
dependencies:
- caniuse-lite "^1.0.30001265"
- electron-to-chromium "^1.3.867"
+ caniuse-lite "^1.0.30001271"
+ electron-to-chromium "^1.3.878"
escalade "^3.1.1"
- node-releases "^2.0.0"
+ node-releases "^2.0.1"
picocolors "^1.0.0"
bser@2.1.1:
@@ -7504,10 +7523,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
-caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001265:
- version "1.0.30001270"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001270.tgz#cc9c37a4ec5c1a8d616fc7bace902bb053b0cdea"
- integrity sha512-TcIC7AyNWXhcOmv2KftOl1ShFAaHQYcB/EPL/hEyMrcS7ZX0/DvV1aoy6BzV0+16wTpoAyTMGDNAJfSqS/rz7A==
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001271:
+ version "1.0.30001271"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001271.tgz#0dda0c9bcae2cf5407cd34cac304186616cc83e8"
+ integrity sha512-BBruZFWmt3HFdVPS8kceTBIguKxu4f99n5JNp06OlPD/luoAMIaIK5ieV5YjnBLH3Nysai9sxj9rpJj4ZisXOA==
capture-exit@^2.0.0:
version "2.0.0"
@@ -8763,7 +8782,7 @@ debug@^3.0.0, debug@^3.0.1, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6:
dependencies:
ms "^2.1.1"
-debuglog@^1.0.1:
+debuglog@*, debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
@@ -9344,10 +9363,10 @@ electron-rebuild@^2.0.3:
tar "^6.0.5"
yargs "^16.0.0"
-electron-to-chromium@^1.3.867:
- version "1.3.868"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.868.tgz#ed835023b57ecf0ba63dfe7d50e16b53758ab1da"
- integrity sha512-kZYCHqwJ1ctGrYDlOcWQH+/AftAm/KD4lEnLDNwS0kKwx1x6dU4zv+GuDjsPPOGn/2TjnKBaZjDyjXaoix0q/A==
+electron-to-chromium@^1.3.878:
+ version "1.3.878"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.878.tgz#baa9fb5c24b9b580f08fb245cbb52a22f8fc8fa8"
+ integrity sha512-O6yxWCN9ph2AdspAIszBnd9v8s11hQx8ub9w4UGApzmNRnoKhbulOWqbO8THEQec/aEHtvy+donHZMlh6l1rbA==
element-resize-detector@^1.2.2:
version "1.2.3"
@@ -10006,6 +10025,16 @@ ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.1.2, ember-co
fs-extra "^9.1.0"
semver "^5.4.1"
+ember-composable-helpers@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/ember-composable-helpers/-/ember-composable-helpers-4.5.0.tgz#94febbdf4348e64f45f7a6f993f326e32540a61e"
+ integrity sha512-XjpDLyVPsLCy6kd5dIxZonOECCO6AA5sY5Hr6tYUbJg3s5ghFAiFWaNcYraYC+fL2yPJQAswwpfwGlQORUJZkw==
+ dependencies:
+ "@babel/core" "^7.0.0"
+ broccoli-funnel "2.0.1"
+ ember-cli-babel "^7.26.3"
+ resolve "^1.10.0"
+
ember-concurrency@^0.10.0:
version "0.10.1"
resolved "https://registry.yarnpkg.com/ember-concurrency/-/ember-concurrency-0.10.1.tgz#aae4528540391a7278e2c193a146b5474cad5ec2"
@@ -13576,7 +13605,7 @@ import-lazy@^4.0.0:
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153"
integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==
-imurmurhash@^0.1.4:
+imurmurhash@*, imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
@@ -15364,6 +15393,11 @@ lodash._baseflatten@^3.0.0:
lodash.isarguments "^3.0.0"
lodash.isarray "^3.0.0"
+lodash._baseindexof@*:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
+ integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=
+
lodash._baseuniq@~4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
@@ -15372,11 +15406,16 @@ lodash._baseuniq@~4.6.0:
lodash._createset "~4.0.0"
lodash._root "~3.0.0"
-lodash._bindcallback@^3.0.0:
+lodash._bindcallback@*, lodash._bindcallback@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=
+lodash._cacheindexof@*:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
+ integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=
+
lodash._createassigner@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11"
@@ -15386,12 +15425,19 @@ lodash._createassigner@^3.0.0:
lodash._isiterateecall "^3.0.0"
lodash.restparam "^3.0.0"
+lodash._createcache@*:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
+ integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
+ dependencies:
+ lodash._getnative "^3.0.0"
+
lodash._createset@~4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=
-lodash._getnative@^3.0.0:
+lodash._getnative@*, lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
@@ -15609,7 +15655,7 @@ lodash.pick@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=
-lodash.restparam@^3.0.0:
+lodash.restparam@*, lodash.restparam@^3.0.0:
version "3.6.1"
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=
@@ -16424,13 +16470,20 @@ minipass@^2.2.0, minipass@^2.3.5:
safe-buffer "^5.1.2"
yallist "^3.0.0"
-minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
+minipass@^3.0.0, minipass@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
dependencies:
yallist "^4.0.0"
+minipass@^3.1.0, minipass@^3.1.3:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.5.tgz#71f6251b0a33a49c01b3cf97ff77eda030dff732"
+ integrity sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==
+ dependencies:
+ yallist "^4.0.0"
+
minizlib@^2.0.0, minizlib@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
@@ -16844,10 +16897,10 @@ node-pre-gyp@^0.11.0:
semver "^5.3.0"
tar "^4"
-node-releases@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.0.tgz#67dc74903100a7deb044037b8a2e5f453bb05400"
- integrity sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA==
+node-releases@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
+ integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
node-uuid@~1.4.7:
version "1.4.8"