From ce121190f7e6ddf3832862aff8495aea3b238451 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 25 Aug 2020 22:36:56 -0400 Subject: [PATCH 1/2] feat: implement IntersectionObserver & IntersectionObserverEntry binding --- CHANGELOG.md | 4 ++ .../Webapi__IntersectionObserver__test.js | 49 +++++++++++++++++++ package.json | 2 +- src/Webapi.re | 2 + ...tionObserver__IntersectionObserverEntry.re | 15 ++++++ src/Webapi/Webapi__IntersectionObserver.re | 36 ++++++++++++++ .../Webapi__IntersectionObserver__test.re | 31 ++++++++++++ 7 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 lib/js/tests/Webapi/Webapi__IntersectionObserver__test.js create mode 100644 src/Webapi/IntersectionObserver/Webapi__IntersectionObserver__IntersectionObserverEntry.re create mode 100644 src/Webapi/Webapi__IntersectionObserver.re create mode 100644 tests/Webapi/Webapi__IntersectionObserver__test.re diff --git a/CHANGELOG.md b/CHANGELOG.md index 42842ca1..2ce9c260 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### 0.20.0 + +* Added binding for `IntersectionObserver` and `IntersectionObserverEntry` + ### 0.19.1 * Removed dev dependency on `bsdoc` to allow smooth installs on non-Mac diff --git a/lib/js/tests/Webapi/Webapi__IntersectionObserver__test.js b/lib/js/tests/Webapi/Webapi__IntersectionObserver__test.js new file mode 100644 index 00000000..6871c778 --- /dev/null +++ b/lib/js/tests/Webapi/Webapi__IntersectionObserver__test.js @@ -0,0 +1,49 @@ +'use strict'; + +var Belt_Option = require("bs-platform/lib/js/belt_Option.js"); +var Caml_option = require("bs-platform/lib/js/caml_option.js"); +var TestHelpers = require("../testHelpers.js"); +var Webapi__Dom__Document = require("../../src/Webapi/Dom/Webapi__Dom__Document.js"); + +var el = document.createElement("div"); + +var body = TestHelpers.unsafelyUnwrapOption(Belt_Option.flatMap(Webapi__Dom__Document.asHtmlDocument(document), (function (prim) { + return Caml_option.nullable_to_opt(prim.body); + }))); + +el.innerText = "Hello There"; + +el.setAttribute("style", "margin-top: 800px; margin-bottom: 800px;"); + +body.appendChild(el); + +function handler(entries, observer) { + entries.forEach((function (entry) { + console.log(entry.time); + console.log(entry.rootBounds); + console.log(entry.boundingClientRect); + console.log(entry.intersectionRect); + console.log(entry.isIntersecting); + console.log(entry.intersectionRatio); + console.log(entry.target); + + })); + observer.unobserve(el); + +} + +var observer = new IntersectionObserver(handler); + +observer.observe(el); + +observer.unobserve(el); + +observer.observe(el); + +observer.disconnect(); + +exports.el = el; +exports.body = body; +exports.handler = handler; +exports.observer = observer; +/* el Not a pure module */ diff --git a/package.json b/package.json index 610bb5f0..3ae2f5a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bs-webapi", - "version": "0.19.1", + "version": "0.20.0", "description": "Reason + BuckleScript bindings to DOM", "repository": { "type": "git", diff --git a/src/Webapi.re b/src/Webapi.re index 00ccfa56..0ca29c14 100644 --- a/src/Webapi.re +++ b/src/Webapi.re @@ -26,6 +26,8 @@ module Performance = Webapi__Performance; /** @since 0.19.0 */ module ReadableStream = Webapi__ReadableStream; +/** @since 0.20.0 */ +module IntersectionObserver = Webapi__IntersectionObserver; module ResizeObserver = Webapi__ResizeObserver; module Url = Webapi__Url; diff --git a/src/Webapi/IntersectionObserver/Webapi__IntersectionObserver__IntersectionObserverEntry.re b/src/Webapi/IntersectionObserver/Webapi__IntersectionObserver__IntersectionObserverEntry.re new file mode 100644 index 00000000..dc7b44fb --- /dev/null +++ b/src/Webapi/IntersectionObserver/Webapi__IntersectionObserver__IntersectionObserverEntry.re @@ -0,0 +1,15 @@ +/** + * Spec: https://www.w3.org/TR/intersection-observer/#intersection-observer-entry + */ + +type t; // TODO: Dom.intersectionObserverEntry + +/* Properties */ + +[@bs.get] external time: t => float = "time"; +[@bs.get] external rootBounds: t => Dom.domRect = "rootBounds"; +[@bs.get] external boundingClientRect: t => Dom.domRect = "boundingClientRect"; +[@bs.get] external intersectionRect: t => Dom.domRect = "intersectionRect"; +[@bs.get] external isIntersecting: t => bool = "isIntersecting"; +[@bs.get] external intersectionRatio: t => float = "intersectionRatio"; +[@bs.get] external target: t => Dom.element = "target"; diff --git a/src/Webapi/Webapi__IntersectionObserver.re b/src/Webapi/Webapi__IntersectionObserver.re new file mode 100644 index 00000000..aeeb9e23 --- /dev/null +++ b/src/Webapi/Webapi__IntersectionObserver.re @@ -0,0 +1,36 @@ +/** + * Spec: https://www.w3.org/TR/intersection-observer/ + */ +/** @since 0.20.0 */ +module IntersectionObserverEntry = Webapi__IntersectionObserver__IntersectionObserverEntry; + +type t; // TODO: Dom.intersectionObserver + +type init = { + root: option(Dom.element), + rootMargin: option(string), + threshold: option(array(float)) // between 0 and 1. +}; + +[@bs.obj] +external makeInit: (~root: Dom.element=?, ~rootMargin: string=?, ~threshold: array(float)=?, unit) => init; + +[@bs.new] +external make: ((. array(IntersectionObserverEntry.t), t) => unit) => t = "IntersectionObserver"; + +[@bs.new] +external makeWithInit: ((. array(IntersectionObserverEntry.t), t) => unit, init) => t = "IntersectionObserver"; + +/* Properties */ + +[@bs.get] [@bs.return nullable] +external root: t => option(Dom.element) = "root"; +[@bs.get] external rootMargin: t => string = "rootMargin"; +[@bs.get] external thresholds: t => array(float) = "thresholds"; + +/* Methods */ + +[@bs.send] external disconnect: t => unit = "disconnect"; +[@bs.send] external observe: (t, Dom.element) => unit = "observe"; +[@bs.send] external unobserve: (t, Dom.element) => unit = "unobserve"; +[@bs.send] external takeRecords: t => array(IntersectionObserverEntry.t) = "takeRecords"; diff --git a/tests/Webapi/Webapi__IntersectionObserver__test.re b/tests/Webapi/Webapi__IntersectionObserver__test.re new file mode 100644 index 00000000..cdb7fd97 --- /dev/null +++ b/tests/Webapi/Webapi__IntersectionObserver__test.re @@ -0,0 +1,31 @@ +let el = Webapi.Dom.document |> Webapi.Dom.Document.createElement("div"); + +let body = + Webapi.Dom.Document.asHtmlDocument(Webapi.Dom.document)->Belt.Option.flatMap(Webapi.Dom.HtmlDocument.body)->TestHelpers.unsafelyUnwrapOption; + +Webapi.Dom.Element.setInnerText(el, "Hello There"); +Webapi.Dom.Element.setAttribute("style", "margin-top: 800px; margin-bottom: 800px;", el); +Webapi.Dom.Element.appendChild(el, body); + +let handler = + (. entries, observer) => { + Js.Array.forEach(entry => { + Js.log(Webapi.IntersectionObserver.IntersectionObserverEntry.time(entry)); + Js.log(Webapi.IntersectionObserver.IntersectionObserverEntry.rootBounds(entry)); + Js.log(Webapi.IntersectionObserver.IntersectionObserverEntry.boundingClientRect(entry)); + Js.log(Webapi.IntersectionObserver.IntersectionObserverEntry.intersectionRect(entry)); + Js.log(Webapi.IntersectionObserver.IntersectionObserverEntry.isIntersecting(entry)); + Js.log(Webapi.IntersectionObserver.IntersectionObserverEntry.intersectionRatio(entry)); + Js.log(Webapi.IntersectionObserver.IntersectionObserverEntry.target(entry)); + }, entries); + + Webapi.IntersectionObserver.unobserve(observer, el); + }; + +let observer = + Webapi.IntersectionObserver.make(handler); + +Webapi.IntersectionObserver.observe(observer, el); +Webapi.IntersectionObserver.unobserve(observer, el); +Webapi.IntersectionObserver.observe(observer, el); +Webapi.IntersectionObserver.disconnect(observer); From 6096ae2f3b9a6b63c11178b3fc9656f3838adeae Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 25 Aug 2020 22:52:34 -0400 Subject: [PATCH 2/2] chore: add note for changing to Dom phantom type for ResizeObserver --- .../Webapi__ResizeObserver__ResizeObserverEntry.re | 2 +- src/Webapi/Webapi__ResizeObserver.re | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Webapi/ResizeObserver/Webapi__ResizeObserver__ResizeObserverEntry.re b/src/Webapi/ResizeObserver/Webapi__ResizeObserver__ResizeObserverEntry.re index ca235441..e03846a4 100644 --- a/src/Webapi/ResizeObserver/Webapi__ResizeObserver__ResizeObserverEntry.re +++ b/src/Webapi/ResizeObserver/Webapi__ResizeObserver__ResizeObserverEntry.re @@ -1,4 +1,4 @@ -type t; +type t; // TODO: Dom.resizeObserverEntry [@bs.get] external contentRect: t => Dom.domRect = ""; [@bs.get] external target: t => Dom.element = ""; diff --git a/src/Webapi/Webapi__ResizeObserver.re b/src/Webapi/Webapi__ResizeObserver.re index 7ea6f104..c5d6e0af 100644 --- a/src/Webapi/Webapi__ResizeObserver.re +++ b/src/Webapi/Webapi__ResizeObserver.re @@ -1,6 +1,6 @@ module ResizeObserverEntry = Webapi__ResizeObserver__ResizeObserverEntry; -type t; +type t; // TODO: Dom.resizeObserver [@bs.new] external make: (array(ResizeObserverEntry.t) => unit) => t = "ResizeObserver";