From c187b483f6c3c765bfaf584077dfac4563746731 Mon Sep 17 00:00:00 2001 From: Michelle Saad Date: Wed, 4 Mar 2020 09:18:14 -0500 Subject: [PATCH 1/7] add arrayLens and optionLens --- src/lens.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lens.js b/src/lens.js index 4a5ed506..6acdd794 100644 --- a/src/lens.js +++ b/src/lens.js @@ -14,6 +14,13 @@ export let objectLens = val => ({ val = x }, }) +export let arrayLens = val => { + let result = [val] + result.push(x => { + result[0] = x + }) + return result +} // Lens Conversion export let fnToObj = fn => ({ @@ -52,6 +59,11 @@ export let includeLens = (value, ...lens) => ({ set: x => set(_.uniq(toggleElementBy(!x, value, view(...lens))), ...lens), }) +export let optionLens = (value, ...lens) => ({ + get: () => _.equals(value, view(...lens)), + set: x => set(x ? value : null, ...lens) +}) + // Lens Manipulation //let construct = (...lens) => (lens[1] ? lensProp(...lens) : lens[0]) let lensPair = (get, set) => ({ get, set }) From d8e3d9025e9213b47aa2872ed5e6c11722c114a5 Mon Sep 17 00:00:00 2001 From: Michelle Saad Date: Wed, 4 Mar 2020 09:18:20 -0500 Subject: [PATCH 2/7] lens tests --- test/lens.spec.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/test/lens.spec.js b/test/lens.spec.js index fb12aace..08113261 100644 --- a/test/lens.spec.js +++ b/test/lens.spec.js @@ -19,6 +19,12 @@ describe('Lens Functions', () => { l.set(5) expect(l.get()).to.equal(5) }) + it('arrayLens', () => { + let l = F.arrayLens(1) + expect(l[0]).to.equal(1) + l[1](5) + expect(l[0]).to.equal(5) + }) }) describe('Conversion', () => { it('fnToObj', () => { @@ -78,6 +84,21 @@ describe('Lens Functions', () => { expect(F.view(includesB)).to.be.true expect(object.arr).to.deep.equal(['a', 'c', 'd', 'b']) }) + it('optionLens', () => { + let object = { selected: 'a' } + let optionA = F.optionLens('a', 'selected', object) + let optionB = F.optionLens('b', 'selected', object) + expect(F.view(optionA)).to.be.true + expect(F.view(optionB)).to.be.false + F.on(optionB)() + expect(F.view(optionA)).to.be.false + expect(F.view(optionB)).to.be.true + expect(object.selected).to.equal('b') + F.off(optionB)() + expect(F.view(optionA)).to.be.false + expect(F.view(optionB)).to.be.false + expect(object.selected).to.deep.equal(null) + }) }) describe('Manipulation', () => { it('view', () => { @@ -196,14 +217,7 @@ describe('Lens Functions', () => { }) describe('additional implicit lens formats', () => { it('arrayLens', () => { - let arrayLens = val => { - let result = [val] - result.push(x => { - result[0] = x - }) - return result - } - let lens = arrayLens(false) + let lens = F.arrayLens(false) F.on(lens)() expect(lens[0]).to.be.true F.off(lens)() From 409a40994a779211adcbd3fbdf5074549333e976 Mon Sep 17 00:00:00 2001 From: Michelle Saad Date: Wed, 4 Mar 2020 09:38:39 -0500 Subject: [PATCH 3/7] update readme --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 1b1eb506..9a2667fe 100644 --- a/README.md +++ b/README.md @@ -627,6 +627,10 @@ Returns a function that will set a lens to `false` `value -> arrayLens -> includeLens` An include lens represents membership of a value in a set. It takes a value and lens and returns a new lens - kind of like a "writeable computed" from MobX or Knockout. The view and set functions allow you to read and write a boolean value for whether or not a value is in an array. If you change to true or false, it will set the underlying array lens with a new array either without the value or with it pushed at the end. +#### optionLens +`value -> arrayLens -> optionLens` +Like `includeLens`, `optionLens` takes a value and lens and returns a new lens. The view and set functions allow you to read and write a boolean value for whether the value passed to the `optionLens` is currently selected (meaning whether it matches the value stored in the underlying lens). Changing the `optionLens` to true "selects" its value (sets the value of the underlying lens to it). + #### domLens.value `lens -> {value, onChange}` Takes a lens and returns a value/onChange pair that views/sets the lens appropriately. `onChange` sets with `e.target.value` (or `e` if that path isn't present). Example: @@ -658,6 +662,9 @@ Takes a value and returns a function lens for that value. Mostly used for testin ### objectLens Takes a value and returns a object lens for that value. Mostly used for testing and mocking purposes. +### arrayLens +Takes a value and returns an array lens for that value. Mostly used for testing and mocking purposes. + ### stateLens `([value, setValue]) -> lens` Given the popularity of React, we decided to include this little helper that converts a `useState` hook call to a lens. Ex: `let lens = stateLens(useState(false))`. You generally won't use this directly since you can pass the `[value, setter]` pair directly to lens functions From e8174563fac9c043c5d09832c20ce48e352bc7df Mon Sep 17 00:00:00 2001 From: Michelle Saad Date: Wed, 4 Mar 2020 09:40:38 -0500 Subject: [PATCH 4/7] update version --- CHANGELOG.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 536ae9fe..966510dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.67.0 +- Add `objectLens` + # 1.66.3 - Use deep comparison on F.{simple,}diff diff --git a/package.json b/package.json index 1ec0f8e0..ed671963 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "futil-js", - "version": "1.66.3", + "version": "1.67.0", "description": "F(unctional) util(ities). Resistance is futile.", "main": "lib/futil-js.js", "scripts": { From 512e2cc4904094c031c456227ebf3c532fb5c643 Mon Sep 17 00:00:00 2001 From: Michelle Saad Date: Wed, 4 Mar 2020 11:23:20 -0500 Subject: [PATCH 5/7] clarify setting optionLens to false --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a2667fe..4ad399b5 100644 --- a/README.md +++ b/README.md @@ -629,7 +629,7 @@ An include lens represents membership of a value in a set. It takes a value and #### optionLens `value -> arrayLens -> optionLens` -Like `includeLens`, `optionLens` takes a value and lens and returns a new lens. The view and set functions allow you to read and write a boolean value for whether the value passed to the `optionLens` is currently selected (meaning whether it matches the value stored in the underlying lens). Changing the `optionLens` to true "selects" its value (sets the value of the underlying lens to it). +Like `includeLens`, `optionLens` takes a value and lens and returns a new lens. The view and set functions allow you to read and write a boolean value for whether the value passed to the `optionLens` is currently selected (meaning whether it matches the value stored in the underlying lens). Setting the `optionLens` to true "selects" its value (sets the value of the underlying lens to it); setting it to false sets the underlying value to `null`. #### domLens.value `lens -> {value, onChange}` Takes a lens and returns a value/onChange pair that views/sets the lens appropriately. `onChange` sets with `e.target.value` (or `e` if that path isn't present). From a2d4b3ff1b1f45c197193fcb1580b9049ee3e2d6 Mon Sep 17 00:00:00 2001 From: Decrapifier Date: Wed, 4 Mar 2020 16:28:20 +0000 Subject: [PATCH 6/7] Automagically formatted by Duti! https://github.com/smartprocure/duti --- src/lens.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lens.js b/src/lens.js index 6acdd794..2cddd922 100644 --- a/src/lens.js +++ b/src/lens.js @@ -61,7 +61,7 @@ export let includeLens = (value, ...lens) => ({ export let optionLens = (value, ...lens) => ({ get: () => _.equals(value, view(...lens)), - set: x => set(x ? value : null, ...lens) + set: x => set(x ? value : null, ...lens), }) // Lens Manipulation From 242f3d96d2df265598a27f0a897f98e83bc8b18a Mon Sep 17 00:00:00 2001 From: Michelle Saad Date: Thu, 5 Mar 2020 13:07:41 -0500 Subject: [PATCH 7/7] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ed671963..5d5a70a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "futil-js", - "version": "1.67.0", + "version": "1.68.0", "description": "F(unctional) util(ities). Resistance is futile.", "main": "lib/futil-js.js", "scripts": {