diff --git a/CHANGELOG.md b/CHANGELOG.md index 72aafb3a..e5e3f1cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Done: * Remove deprecated APIs * `Window.getSelection` now returns an option, to better match the definition * Add scrollToWithOptions to window +* Added IntersectionObserver and IntersectionObserverEntry bindings Todo: * Convert to rescript syntax 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..357f0ff7 --- /dev/null +++ b/lib/js/tests/Webapi/Webapi__IntersectionObserver__test.js @@ -0,0 +1,49 @@ +'use strict'; + +var Belt_Option = require("rescript/lib/js/belt_Option.js"); +var Caml_option = require("rescript/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/src/Webapi.res b/src/Webapi.res index 2a51419d..5e3a0039 100644 --- a/src/Webapi.res +++ b/src/Webapi.res @@ -26,6 +26,7 @@ module Performance = Webapi__Performance /** @since 0.19.0 */ module ReadableStream = Webapi__ReadableStream +module IntersectionObserver = Webapi__IntersectionObserver module ResizeObserver = Webapi__ResizeObserver module Url = Webapi__Url diff --git a/src/Webapi/Webapi__IntersectionObserver.res b/src/Webapi/Webapi__IntersectionObserver.res new file mode 100644 index 00000000..1da206b3 --- /dev/null +++ b/src/Webapi/Webapi__IntersectionObserver.res @@ -0,0 +1,61 @@ +/** + * Spec: https://www.w3.org/TR/intersection-observer/ + */ + +module IntersectionObserverEntry = { + /** + * Spec: https://www.w3.org/TR/intersection-observer/#intersection-observer-entry + */ + + type t = Dom.intersectionObserverEntry + + /* Properties */ + + @get external time: t => float = "time" + @get external rootBounds: t => Dom.domRect = "rootBounds" + @get external boundingClientRect: t => Dom.domRect = "boundingClientRect" + @get external intersectionRect: t => Dom.domRect = "intersectionRect" + @get external isIntersecting: t => bool = "isIntersecting" + @get external intersectionRatio: t => float = "intersectionRatio" + @get external target: t => Dom.element = "target" +} + +type t = Dom.intersectionObserver + +type intersectionObserverInit = { + root: option, + rootMargin: option, + threshold: option>, // between 0 and 1. +} + +@obj +external makeInit: ( + ~root: Dom.element=?, + ~rootMargin: string=?, + ~threshold: array=?, + unit, +) => intersectionObserverInit = "" + +@new +external make: (@uncurry (array, t) => unit) => t = + "IntersectionObserver" + +@new +external makeWithInit: ( + @uncurry (array, t) => unit, + intersectionObserverInit, +) => t = "IntersectionObserver" + +/* Properties */ + +@get @return(nullable) +external root: t => option = "root" +@get external rootMargin: t => string = "rootMargin" +@get external thresholds: t => array = "thresholds" + +/* Methods */ + +@send external disconnect: t => unit = "disconnect" +@send external observe: (t, Dom.element) => unit = "observe" +@send external unobserve: (t, Dom.element) => unit = "unobserve" +@send external takeRecords: t => array = "takeRecords" diff --git a/tests/Webapi/Webapi__IntersectionObserver__test.res b/tests/Webapi/Webapi__IntersectionObserver__test.res new file mode 100644 index 00000000..6b324383 --- /dev/null +++ b/tests/Webapi/Webapi__IntersectionObserver__test.res @@ -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(el, "style", "margin-top: 800px; margin-bottom: 800px") +Webapi.Dom.Element.appendChild(body, el) + +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)