Skip to content

Examples

The best example of usage of these bindings are the tests.
These exercise the public bindings directly. Reusable Web API bindings and conversion helpers belong in the library rather than in individual examples.

AddEventListener__test

let button = DomGlobal.document->Document.querySelector("button")->Null.toOption
let h2 = DomGlobal.document->Document.querySelector("h2")->Null.toOption
switch (button, h2) {
| (Some(button), Some(h2)) =>
button->Element.addEventListener(EventType.Click, (e: UiEventsTypes.mouseEvent) => {
Console.log(`Button clicked, ${Int.toString(e.button)}`)
switch h2.textContent {
| Null => h2.textContent = Value("1")
| Value(text) =>
switch Int.fromString(text) {
| None => h2.textContent = Value("1")
| Some(number) => h2.textContent = Value(Int.toString(number + 1))
}
}
})
| _ => Console.log("Stuff not found")
}

AudioDestinationNode__.test

let ctx = AudioContext.make()
let destinationNode = ctx.destination->AudioDestinationNode.asAudioNode
let context = AudioContext.asBaseAudioContext(ctx)
let osc = OscillatorNode.make(
~context,
~options={
type_: WebAudioTypes.Sine,
frequency: 440.0,
},
)
let gain = GainNode.make(
~context,
~options={
gain: 0.3,
},
)
let _ = gain->GainNode.connect(~destinationNode)
let _ =
osc
->OscillatorNode.asAudioScheduledSourceNode
->AudioScheduledSourceNode.connect(~destinationNode=gain->GainNode.asAudioNode)
osc->OscillatorNode.start

BindingAbsence__test

let requestWithNullBody: Request.requestInit = {body: Nullable.null}
let requestWithUndefinedBody: Request.requestInit = {body: Nullable.undefined}
let intersectionWithNullRoot: IntersectionObserverTypes.intersectionObserverInit = {
root: Nullable.null,
}
let waveShaperWithCurve: WebAudioTypes.waveShaperOptions = {curve: [0., 1.]}
let decodingConfiguration = (
info: MediaCapabilities.Types.mediaCapabilitiesDecodingInfo,
): MediaCapabilities.Types.mediaDecodingConfiguration => info.configuration
let decodingKeySystemAccess = (info: MediaCapabilities.Types.mediaCapabilitiesDecodingInfo): Null.t<
BaseEncryptedMediaExtensions.mediaKeySystemAccess,
> => info.keySystemAccess
let encodingConfiguration = (
info: MediaCapabilities.Types.mediaCapabilitiesEncodingInfo,
): MediaCapabilities.Types.mediaEncodingConfiguration => info.configuration
let sharedWorkerName = (scope: SharedWorkerScope.t): string => scope.name
let imagePattern = (context: DOM.canvasRenderingContext2D, image: HTMLImageElement.t): Null.t<
CanvasTypes.canvasPattern,
> => context->CanvasRenderingContext2D.createPattern(~image, ~repetition="repeat")

Classify__test

%%raw(`
globalThis.Element = class Element {}
globalThis.Document = class Document {}
globalThis.HTMLElement = class HTMLElement extends globalThis.Element {}
globalThis.HTMLCanvasElement = class HTMLCanvasElement extends globalThis.HTMLElement {}
globalThis.HTMLImageElement = class HTMLImageElement extends globalThis.HTMLElement {}
globalThis.HTMLInputElement = class HTMLInputElement extends globalThis.HTMLElement {
checkValidity() {
return true
}
}
`)
let element: unknown = %raw(`new globalThis.Element()`)
let document: unknown = %raw(`new globalThis.Document()`)
let htmlElement: unknown = %raw(`new globalThis.HTMLElement()`)
let canvas: unknown = %raw(`new globalThis.HTMLCanvasElement()`)
let image: unknown = %raw(`new globalThis.HTMLImageElement()`)
let input: unknown = %raw(`new globalThis.HTMLInputElement()`)
assert(element->Element.classify->Option.isSome)
assert(document->Document.classify->Option.isSome)
assert(htmlElement->HTMLElement.classify->Option.isSome)
assert(canvas->HTMLCanvasElement.classify->Option.isSome)
assert(image->HTMLImageElement.classify->Option.isSome)
assert(input->HTMLInputElement.classify->Option.isSome)
assert(input->Element.classify->Option.isSome)
assert(input->HTMLElement.classify->Option.isSome)
assert(document->Element.classify->Option.isNone)
assert(image->HTMLCanvasElement.classify->Option.isNone)
assert(htmlElement->HTMLInputElement.classify->Option.isNone)
input
->HTMLInputElement.classify
->Option.forEach(input => assert(input->HTMLInputElement.checkValidity))
%%raw(`
delete globalThis.HTMLCanvasElement
delete globalThis.HTMLImageElement
delete globalThis.HTMLInputElement
`)
assert(canvas->HTMLCanvasElement.classify->Option.isNone)
assert(image->HTMLImageElement.classify->Option.isNone)
assert(input->HTMLInputElement.classify->Option.isNone)

Document__test

let createSvgElement = (document: DOM.document) =>
document->Document.createElementNS(~namespace="http://www.w3.org/2000/svg", ~qualifiedName="svg")
let makeAnimation = (timeline: Animation.animationTimeline) => Animation.make(~timeline)
let asAnimationTimeline = (timeline: DOM.documentTimeline): Animation.animationTimeline =>
timeline->DocumentTimeline.asAnimationTimeline

DOMMatrix__test

let _make = DOMMatrix.make()
let _fromString = DOMMatrix.fromString("matrix(1, 0, 0, 1, 0, 0)")
let _fromArray = DOMMatrix.fromArray([1., 0., 0., 1., 0., 0.])

DOMMatrixReadOnly__test

let _make = DOMMatrixReadOnly.make()
let _fromString = DOMMatrixReadOnly.fromString("matrix(1, 0, 0, 1, 0, 0)")
let _fromArray = DOMMatrixReadOnly.fromArray([1., 0., 0., 1., 0., 0.])

Element__test

external myElement: DOMTree.element = "myElement"
switch myElement->Element.getAttribute("foo") {
| Null.Value(value) => value->Console.log
| Null => "nothing"->Console.log
}

Event__test

let acceptsDOMEvent = (_event: DOM.event) => ()
let acceptsDOMExtendableEvent = (_event: DOM.extendableEvent) => ()
let _ = (event: PushEvent.t) => {
acceptsDOMEvent(event->PushEvent.asEvent)
acceptsDOMExtendableEvent(event->PushEvent.asExtendableEvent)
}
let handleClick = (event: DOM.event) => {
event->Event.preventDefault
switch event->Event.target {
| Value(target) => Console.log(target)
| Null => Console.log("No target found")
}
}
let target: DOM.eventTarget = {}
let fn = (target: DOM.eventTarget) =>
target->EventTarget.addEventListener(Click, () => Console.log("Click 1"))
let x = fn(target)
// Testing out global event listeners
DOM.window->Window.addEventListener(Click, () => Console.log("Click 2"))

EventTarget__test

let acceptsDOMEventTarget = (_target: DOM.eventTarget) => ()
let acceptsEventTargetLeaf = (_target: DOM.eventTarget) => ()
let _ = (target: DOM.eventTarget) => {
acceptsEventTargetLeaf(target)
}
let _ = (target: DOM.eventTarget) => {
acceptsDOMEventTarget(target)
}
let el = switch Document.make()->Document.getElementById("foo") {
| Null => ()
| Value(el) => el->Element.addEventListener(Click, () => ())
}

EventType__test

let click: EventType.t = Click
let custom: EventType.t = Custom("custom-event")
let _ = (click, custom)

Fetch__test

let response = await Fetch.fetch("https://rescript-lang.org/")
let response2 = await Fetch.fetch(
"https://rescript-lang.org/",
~init={
headers: HeadersInit.fromDict(
dict{
"Content-Type": "application/json",
"Authorization": "Bearer token",
},
),
body: BodyInit.fromString(`secret=foo&response=bar`)->Nullable.make,
},
)
let response3 = await Fetch.fetchWithRequest(
Request.fromURL("https://rescript-lang.org/"),
~init={
method: "POST",
headers: HeadersInit.fromDict(
dict{
"Content-Type": "application/x-www-form-urlencoded",
},
),
body: BodyInit.fromString(`secret=foo&response=bar`)->Nullable.make,
},
)
DOM.window->Window.removeEventListener(
EventType.Mousedown,
MouseEvent.preventDefault,
~options={capture: false},
)
let registrationResult = await Window.current
->Window.navigator
->Navigator.serviceWorker
->ServiceWorkerContainer.register("/sw.js")
let subscription = await registrationResult.pushManager->PushManager.subscribe(
~options={
userVisibleOnly: true,
applicationServerKey: ApplicationServerKey.fromString("MyPublicKey")->Nullable.make,
},
)
let pushSubscriptionJSON = subscription->PushSubscription.toJSON
let (auth, p256dh) = switch pushSubscriptionJSON.keys {
| None => ("?", "?")
| Some(keys) => (keys.auth, keys.p256dh)
}
Console.log(`For subscription ${subscription.endpoint}, auth is ${auth} and p256dh is ${p256dh}`)

FontFace__test

let dataView: DataView.t = Obj.magic()
let arrayBuffer: ArrayBuffer.t = Obj.magic()
let _fromString = FontFace.fromString(~family="Inter", ~source="url(/fonts/inter.woff2)")
let _fromDataView = FontFace.fromDataView(~family="Inter", ~source=dataView)
let _fromArrayBuffer = FontFace.fromArrayBuffer(~family="Inter", ~source=arrayBuffer)

FormData__test

/* This works when your form has an id of "myForm" */
@scope(("document", "forms"))
external myForm: DOMTree.htmlFormElement = "myForm"
module EntryValue = FormDataEntryValue
open EntryValue
let logEntry = (~stringPrefix: string, ~filePrefix: string, entry: EntryValue.t) =>
switch entry {
| String(value) => Console.log(`${stringPrefix}${value}`)
| File(file) => Console.log(`${filePrefix}${file.name}`)
}
let formData: FormData.t = FormData.make(~form=myForm)
// Get a form field - returns formDataEntryValue which could be string or WebApiFile
let phoneEntry: null<EntryValue.t> = formData->FormData.get("phone")
// Decode the entry to handle both string and WebApiFile cases
let _ = switch phoneEntry->Null.toOption {
| None => Console.log("No phone field")
| Some(entry) => logEntry(~stringPrefix="Phone: ", ~filePrefix="Unexpected file: ", entry)
}
// Get all values for a field (useful for multi-select or multiple file inputs)
let allImages: array<EntryValue.t> = formData->FormData.getAll("images")
let _ =
allImages->Array.forEach(entry =>
logEntry(~stringPrefix="String value: ", ~filePrefix="WebApiFile: ", entry)
)
// Create formDataEntryValue from string or file
let stringEntry = EntryValue.String("test value")
let blob: Blob.t = Blob.make(~blobParts=[])
let file: File.t = File.make(~fileBits=[], ~fileName="test.txt")
let fileEntry = EntryValue.File(file)
formData->FormData.appendBlob(~name="avatar", ~blobValue=blob)
logEntry(~stringPrefix="String entry: ", ~filePrefix="Unexpected file entry: ", stringEntry)
logEntry(~stringPrefix="Unexpected string entry: ", ~filePrefix="File entry: ", fileEntry)
// Iterate over all entries in the FormData
let entries: iterable<(string, EntryValue.t)> = formData->FormData.entries
let _ =
entries
->Array.fromIterable
->Array.forEach(((key, value)) => {
switch value {
| String(s) => Console.log(`${key}: ${s}`)
| File(f) => Console.log(`${key}: [WebApiFile] ${f.name}`)
}
})

Headers__test

let h = Headers.make()
h->Headers.set(~name="X-Test", ~value="1")
let h2 = Headers.fromDict(dict{"X-Vegetable": "Carrot"})
let h3 = Headers.fromKeyValueArray([("X-Fruit", "Apple"), ("X-Vegetable", "Carrot")])
Console.log(h3->Headers.get("X-Fruit"))

HTMLCanvasElement__test

let draw = (ctx: DOM.canvasRenderingContext2D) => {
ctx->CanvasRenderingContext2D.setFillStyle(FillStyle.fromString("red"))
ctx->CanvasRenderingContext2D.fillRect(~x=50., ~y=50., ~w=200., ~h=200.)
ctx->CanvasRenderingContext2D.setFillStyle(FillStyle.fromString("black"))
ctx->CanvasRenderingContext2D.setFont("2px Tahoma")
ctx->CanvasRenderingContext2D.setTextBaseline(CanvasTypes.Top)
ctx->CanvasRenderingContext2D.fillText(~text="MY TEXT", ~x=60., ~y=60.)
switch ctx->CanvasRenderingContext2D.getFillStyle->FillStyle.decode {
| FillStyle.String(color) => Console.log(`Color: ${color}`)
| FillStyle.CanvasGradient(_) => Console.log("CanvasGradient")
| FillStyle.CanvasPattern(_) => Console.log("CanvasPattern")
}
DomGlobal.document
->Document.createElement("img")
->HTMLImageElement.classify
->Option.forEach(image =>
ctx->CanvasRenderingContext2D.drawImageWithDimensions(
~image,
~dx=0.,
~dy=0.,
~dw=200.,
~dh=200.,
)
)
}
DomGlobal.document
->Document.getElementById("myCanvas")
->Null.toOption
->Option.flatMap(element => element->HTMLCanvasElement.classify)
->Option.forEach(canvas =>
canvas->HTMLCanvasElement.getContext2D->Null.toOption->Option.forEach(draw)
)

HTMLElement__test

DomGlobal.document
->Document.querySelector("form")
->Null.toOption
->Option.forEach(form => {
form->Element.scrollIntoViewWithOptions({behavior: DOM.Smooth})
})
let asNode = (element: Element.t): Node.t => element->Element.asNode
let asElement = (element: HTMLElement.t): Element.t => element->HTMLElement.asElement
let setNamespacedAttribute = (element: HTMLElement.t) =>
element->HTMLElement.setAttributeNS(
~namespace="http://www.w3.org/1999/xhtml",
~qualifiedName="data-follow-up",
~value="complete",
)

HTMLElementHidden__test

let describeHidden = (element: HTMLElement.t) =>
switch element->HTMLElement.hidden {
| HTMLElement.Visible => "visible"
| HTMLElement.Hidden => "hidden"
| HTMLElement.HiddenUntilFound => "hidden until found"
}
let setHiddenStates = (element: HTMLElement.t) => {
element->HTMLElement.setHidden(HTMLElement.Hidden)
element->HTMLElement.setHidden(HTMLElement.HiddenUntilFound)
element->HTMLElement.setHidden(HTMLElement.Visible)
}
let formHidden = (element: HTMLFormElement.t): HTMLElement.hiddenState =>
element->HTMLFormElement.hidden
let setFormHidden = (element: HTMLFormElement.t) =>
element->HTMLFormElement.setHidden(HTMLElement.Hidden)
let slotHidden = (element: HTMLSlotElement.t): HTMLElement.hiddenState =>
element->HTMLSlotElement.hidden
let setSlotHidden = (element: HTMLSlotElement.t) =>
element->HTMLSlotElement.setHidden(HTMLElement.HiddenUntilFound)
let anchorHidden = (element: HTMLAnchorElement.t): HTMLElement.hiddenState =>
element->HTMLAnchorElement.hidden
let setAnchorHidden = (element: HTMLAnchorElement.t) =>
element->HTMLAnchorElement.setHidden(HTMLElement.Visible)

HTMLInputElement__test

let value = switch DomGlobal.document->Document.createElement("input")->HTMLInputElement.classify {
| Some(input) => Some(input.value)
| None => None
}

HTMLSlotElement__test

let assignedNodesForElement = (element: DOMTree.element) =>
switch element.assignedSlot {
| Value(slot) =>
slot.name = "content"
slot->HTMLSlotElement.assignedNodes
| Null => []
}
let assignedNodesForText = (text: Text.t) =>
switch text.assignedSlot {
| Value(slot) =>
slot.name = "content"
slot->HTMLSlotElement.assignedNodes
| Null => []
}

ImageData__test

let imageData = ImageData.makeWithData(~data=Uint8ClampedArray.fromArray([]), ~sw=100, ~sh=100)
imageData.data->TypedArray.length->Console.log

IntersectionObserver__test

module IObserver = IntersectionObserver
module IRoot = IntersectionObserverRoot
let observer = IObserver.make(~callback=(entry, observer) => {
Console.log2(entry, observer)
})
let root = DomGlobal.document->Document.querySelector("#root")->Null.getUnsafe
let observer2 = IObserver.make(
~callback=(entry, observer) => {
Console.log2(entry, observer)
},
~options={
root: root->IRoot.fromElement->Nullable.make,
rootMargin: "10px",
threshold: [0.1],
},
)
switch observer2.root->Null.toOption {
| Some(root) =>
switch root->IRoot.decode {
| Element(_) => Console.log("Element")
| Document(_) => Console.log("Document")
| Null => Console.log("Null")
}
| None => Console.log("Null")
}
let rootMargin2 = observer2.rootMargin
let targetElement = DomGlobal.document->Document.querySelector("#targetElement")->Null.toOption
switch targetElement {
| Some(e) => {
observer2->IObserver.observe(e)
observer2->IObserver.unobserve(e)
}
| _ => Console.log("Target element not found.")
}
let entries2 = observer2->IObserver.takeRecords
Console.log(entries2->Array.length)
observer2->IObserver.disconnect

Location__test

let window = DOM.window
let location = window->Window.location
// Access properties using `.`
let href = location.href
// Invoke methods using the `->TypeModule`
location->Location.reload
let a = 0
// testing out editor autocomplete
let fn = (l: Location.t) => l->Location.reload

MediaStream__test

let mediaStream: MediaCaptureAndStreamsTypes.mediaStream = Obj.magic()
let mediaStreamTrack: MediaCaptureAndStreamsTypes.mediaStreamTrack = Obj.magic()
let _make = MediaStream.make()
let _fromMediaStream = MediaStream.fromMediaStream(mediaStream)
let _fromTracks = MediaStream.fromTracks([mediaStreamTrack])

MutationObserver__test

module MObserver = MutationObserver
let observer = MObserver.make((mutations, obs) => {
let button = DomGlobal.document->Document.querySelector("button")
switch button->Null.toOption {
| Some(button) => {
Console.log(button)
obs->MObserver.disconnect
}
| None => ()
}
Console.log(mutations)
})
observer->MObserver.observe(
~target=DomGlobal.document->Document.asNode,
~options={childList: true, subtree: true},
)
let records = observer->MObserver.takeRecords
Console.log(records->Array.length)
observer->MObserver.disconnect

Notification__test

let current = Notification.permission
Notification.requestPermission()
->Promise.thenResolve(notificationPermission => {
switch notificationPermission {
| Granted => Console.log("Permission granted")
| Denied => Console.log("Permission denied")
| Default => Console.log("Permission default")
}
})
->Promise.ignore

OfflineAudioContext__test

let offlineAudioContextOptions: WebAudioTypes.offlineAudioContextOptions = Obj.magic()
let _fromOptions = OfflineAudioContext.fromOptions(offlineAudioContextOptions)
let _fromChannelCountLengthAndSampleRate = OfflineAudioContext.fromChannelCountLengthAndSampleRate(
~numberOfChannels=2,
~length=1024,
~sampleRate=44_100.,
)

Path2D__test

let path2D: CanvasTypes.path2D = Obj.magic()
let _make = Path2D.make()
let _fromPath2D = Path2D.fromPath2D(path2D)
let _fromString = Path2D.fromString("M0 0 L10 10")

ReadableStream__test

let underlyingSource: FileTypes.underlyingSource<string> = Obj.magic()
let strategy: FileTypes.queuingStrategy<string> = Obj.magic()
let _make: ReadableStream.t<string> = ReadableStream.make()
let _fromUnderlyingSource = ReadableStream.fromUnderlyingSource(underlyingSource)
let _fromUnderlyingSourceWithStrategy = ReadableStream.fromUnderlyingSource(
underlyingSource,
~strategy,
)

Request__test

let req = Request.fromURL("https://example.com")
let blob = Blob.make(~blobParts=[])
let file = File.make(~fileBits=[], ~fileName="hello.txt")
let params = URLSearchParams.fromString("greeting=hello")
let formData = FormData.make()
let stream = ReadableStream.make()
let stringBody = BodyInit.fromString("hello")
let blobBody = BodyInit.fromBlob(blob)
let fileBody = BodyInit.fromFile(file)
let paramsBody = BodyInit.fromURLSearchParams(params)
let formDataBody = BodyInit.fromFormData(formData)
let streamBody = BodyInit.fromReadableStream(stream)
let req1 = Request.fromURL(
"https://example.com/api",
~init={method: "POST", body: stringBody->Nullable.make},
)
let req2 = Request.fromRequest(req1)
let _blob: Blob.t = await req2->Request.clone->Request.blob
let formDataReq = Request.fromURL(
"https://example.com/form",
~init={method: "POST", body: formDataBody->Nullable.make},
)
let _formData: FormData.t = await formDataReq->Request.formData
Console.log(await req2->Request.text)

Response__test

let headers = HeadersInit.fromDict(dict{"X-Fruit": "Peach"})
let blob = Blob.make(~blobParts=[])
let file = File.make(~fileBits=[], ~fileName="pong.txt")
let params = URLSearchParams.fromString("fruit=peach")
let formData = FormData.make()
let stream = ReadableStream.make()
let response = Response.fromNull(~init={status: 204, headers})
let response1 = Response.fromString("pong", ~init={status: 200, headers})
let response2 = Response.fromBlob(blob)
let response3 = Response.fromFile(file)
let response4 = Response.fromURLSearchParams(params)
let response5 = Response.fromFormData(formData)
let response6 = Response.fromReadableStream(stream)
let _blob: Blob.t = await response1
->Response.clone
->Response.blob
let _formData: FormData.t = await response5->Response.formData

ServiceWorker__test

let self = ServiceWorkerScope.current
self->ServiceWorkerScope.addEventListener(EventType.Push, (event: PushEvent.t) => {
Console.log("received push event")
// Extract data
let (title, body) = switch event.data->Null.toOption {
| Some(data) =>
switch data->PushMessageData.json {
| JSON.Object(dict{"title": JSON.String(title), "body": JSON.String(body)}) => (title, body)
| _ => ("???", "???")
}
| None => ("???", "???")
}
// Handle some data sync
event->PushEvent.waitUntil(self->ServiceWorkerScope.fetch("https://rescript-lang.org"))
// Show notification
self.registration
->ServiceWorkerRegistration.showNotification(
~title,
~options={
body,
icon: "/icon.png",
actions: [{action: "open", title: "Open"}, {action: "close", title: "Close"}],
// For example the id of a new data entry
data: JSON.Number(17.),
vibrate: [200, 50, 200, 50, 400],
},
)
->Promise.ignore
})
self->ServiceWorkerScope.addEventListener(EventType.NotificationClick, (
event: Notification.notificationEvent,
) => {
Console.log(`notification clicked: ${event.action}`)
// Close the notification
event.notification->Notification.close
// Open a new window if that is relevant
event.notification.data
->Option.flatMap(data => {
switch data {
| JSON.Number(id) => Some(Float.toString(id))
| _ => None
}
})
->Option.forEach(id => {
self.clients
->Clients.openWindow(`https://mywebsite.com/mydata/${id}`)
->Promise.ignore
})
})

SharedWorker__test

let shared1: SharedWorker.t = SharedWorker.make("sharedworker.js")
let shared2: SharedWorker.t = SharedWorker.makeWithName("sharedworker.js", "name")
let shared3: SharedWorker.t = SharedWorker.makeWithOptions(
"sharedworker.js",
{
name: "workerName",
type_: WebWorkersTypes.Module,
},
)
let port: MessagePort.t = SharedWorker.port(shared1)
let self = SharedWorkerScope.current
self->SharedWorkerScope.close

SharedWorkerScope__test

let self = SharedWorkerScope.current
self->SharedWorkerScope.close
let workerLocation = Worker.current->Worker.location
let workerHref: string = workerLocation.href
let sharedWorkerLocation = self->SharedWorkerScope.location
let sharedWorkerHref: string = sharedWorkerLocation.href

Storage__test

for i in 0 to DomGlobal.localStorage.length - 1 {
DomGlobal.localStorage->Storage.key(i)->Null.getOr("nothing")->Console.log
}
let item1 = DomGlobal.localStorage->Storage.getItem("foo")->Null.getOr("nothing")
DomGlobal.localStorage->Storage.setItem(~key="bar", ~value="...")
DomGlobal.localStorage->Storage.removeItem("bar")
DomGlobal.localStorage->Storage.clear

SVGElement__test

let getViewBox = (element: SVGElement.t) => element->SVGElement.getAttribute("viewBox")
let graphicsElementAsElement = (element: SVGElement.svgGraphicsElement): DOMTree.element =>
element->SVGGraphicsElement.asSVGElement->SVGElement.asElement
let getGraphicsViewBox = (element: SVGElement.svgGraphicsElement) =>
element->SVGGraphicsElement.getAttribute("viewBox")

URL__test

let url = URL.make(~url="/foo", ~base="https://bar.com")

URLSearchParams__test

let params1 = URLSearchParams.fromString("foo=1&bar=2")
params1->URLSearchParams.keys->Array.fromIterable->Array.forEach(Console.log)
let params2 = URLSearchParams.fromKeyValueArray([("foo", "1"), ("bar", "b")])
params2->URLSearchParams.values->Array.fromIterable->Array.forEach(Console.log)
let params3 = URLSearchParams.fromDict(dict{"foo": "1", "bar": "b"})
params3
->URLSearchParams.entries
->Array.fromIterable
->Array.forEach(((key, value)) => Console.log2(key, value))
let paramStr = params3->URLSearchParams.toString

VideoFrame__test

let htmlImageElement: HTMLImageElement.t = Obj.magic()
let svgImageElement: SVGElement.svgImageElement = Obj.magic()
let htmlVideoElement: HTMLVideoElement.t = Obj.magic()
let htmlCanvasElement: HTMLCanvasElement.t = Obj.magic()
let imageBitmap: CanvasTypes.imageBitmap = Obj.magic()
let offscreenCanvas: CanvasTypes.offscreenCanvas = Obj.magic()
let videoFrame: DOM.videoFrame = Obj.magic()
let arrayBuffer: ArrayBuffer.t = Obj.magic()
let typedArray: TypedArray.t<int> = Obj.magic()
let dataView: DataView.t = Obj.magic()
let videoFrameInit: DOM.videoFrameInit = Obj.magic()
let videoFrameBufferInit: DOM.videoFrameBufferInit = Obj.magic()
let _fromHTMLImageElement = VideoFrame.fromHTMLImageElement(
~image=htmlImageElement,
~init=videoFrameInit,
)
let _fromSVGImageElement = VideoFrame.fromSVGImageElement(
~image=svgImageElement,
~init=videoFrameInit,
)
let _fromHTMLVideoElement = VideoFrame.fromHTMLVideoElement(
~image=htmlVideoElement,
~init=videoFrameInit,
)
let _fromHTMLCanvasElement = VideoFrame.fromHTMLCanvasElement(
~image=htmlCanvasElement,
~init=videoFrameInit,
)
let _fromImageBitmap = VideoFrame.fromImageBitmap(~image=imageBitmap, ~init=videoFrameInit)
let _fromOffscreenCanvas = VideoFrame.fromOffscreenCanvas(
~image=offscreenCanvas,
~init=videoFrameInit,
)
let _fromVideoFrame = VideoFrame.fromVideoFrame(~image=videoFrame, ~init=videoFrameInit)
let _fromArrayBuffer = VideoFrame.fromArrayBuffer(~data=arrayBuffer, ~init=videoFrameBufferInit)
let _fromTypedArray = VideoFrame.fromTypedArray(~data=typedArray, ~init=videoFrameBufferInit)
let _fromDataView = VideoFrame.fromDataView(~data=dataView, ~init=videoFrameBufferInit)

VisualViewport__test

let maybeViewport: Null.t<VisualViewport.t> = DOM.window->Window.visualViewport

WebSocket__test

let _fromURL = WebSocket.fromURL(~url="wss://example.com/socket")
let _fromURLWithProtocols = WebSocket.fromURLWithProtocols(
~url="wss://example.com/socket",
~protocols=["chat", "superchat"],
)