diff --git a/package-lock.json b/package-lock.json
index 9afa0d162..39df72a89 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,6 +16,7 @@
"@headlessui/react": "^2.2.4",
"@mdx-js/loader": "^3.1.0",
"@rescript/react": "^0.14.0-rc.1",
+ "@rescript/webapi": "^0.1.0-experimental-03eae8b",
"codemirror": "^5.54.0",
"docson": "^2.1.0",
"escodegen": "^2.1.0",
@@ -2089,6 +2090,15 @@
"react-dom": ">=19.0.0"
}
},
+ "node_modules/@rescript/webapi": {
+ "version": "0.1.0-experimental-03eae8b",
+ "resolved": "https://registry.npmjs.org/@rescript/webapi/-/webapi-0.1.0-experimental-03eae8b.tgz",
+ "integrity": "sha512-0McQ9XQlbF+/BWs70P2XJZ3wP6us7/HnNWAFnDYSnA9+Rvp6IQAuKCXfhbqJgTIge4YfiY5j+SqDt+OLfsSUTA==",
+ "license": "MIT",
+ "dependencies": {
+ "rescript": "^12.0.0-alpha.13"
+ }
+ },
"node_modules/@rescript/win32-x64": {
"version": "12.0.0-alpha.14",
"resolved": "https://registry.npmjs.org/@rescript/win32-x64/-/win32-x64-12.0.0-alpha.14.tgz",
diff --git a/package.json b/package.json
index dd63efb01..58869e8ac 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"@headlessui/react": "^2.2.4",
"@mdx-js/loader": "^3.1.0",
"@rescript/react": "^0.14.0-rc.1",
+ "@rescript/webapi": "^0.1.0-experimental-03eae8b",
"codemirror": "^5.54.0",
"docson": "^2.1.0",
"escodegen": "^2.1.0",
diff --git a/rescript.json b/rescript.json
index fc09510b1..87790843e 100644
--- a/rescript.json
+++ b/rescript.json
@@ -5,7 +5,11 @@
"version": 4
},
"bs-dependencies": [
- "@rescript/react"
+ "@rescript/react",
+ "@rescript/webapi"
+ ],
+ "bsc-flags": [
+ "-open WebAPI.Global"
],
"sources": [
{
diff --git a/src/ApiDocs.res b/src/ApiDocs.res
index 36f02582c..fba3abf17 100644
--- a/src/ApiDocs.res
+++ b/src/ApiDocs.res
@@ -95,7 +95,7 @@ module SidebarTree = {
let version = url->Url.getVersionString
let moduleRoute =
- Webapi.URL.make("file://" ++ router.asPath).pathname
+ WebAPI.URL.make(~url="file://" ++ router.asPath).pathname
->String.replace(`/docs/manual/${version}/api/`, "")
->String.split("/")
diff --git a/src/ConsolePanel.res b/src/ConsolePanel.res
index 6c72f86f0..8018483db 100644
--- a/src/ConsolePanel.res
+++ b/src/ConsolePanel.res
@@ -17,8 +17,8 @@ let make = (~logs, ~appendLog) => {
| _ => ()
}
}
- Webapi.Window.addEventListener("message", cb)
- Some(() => Webapi.Window.removeEventListener("message", cb))
+ WebAPI.Window.addEventListener(window, Custom("message"), cb)
+ Some(() => WebAPI.Window.removeEventListener(window, Custom("message"), cb))
}, [appendLog])
diff --git a/src/Packages.res b/src/Packages.res
index 7460b704d..7cec69cdc 100644
--- a/src/Packages.res
+++ b/src/Packages.res
@@ -73,7 +73,7 @@ module Resource = {
})
}
- let uniqueKeywords: array
=> array = %raw(`(keywords) => [...new Set(keywords)]`)
+ let uniqueKeywords = arr => arr->Set.fromArray->Set.toArray
let isOfficial = (res: t) => {
switch res {
@@ -340,24 +340,15 @@ module InfoSidebar = {
}
type props = {
- "packages": array,
- "urlResources": array,
- "unmaintained": array,
+ packages: array,
+ urlResources: array,
+ unmaintained: array,
}
type state =
| All
| Filtered(string) // search term
-let scrollToTop: unit => unit = %raw(`function() {
- window.scroll({
- top: 0,
- left: 0,
- behavior: 'smooth'
- });
-}
-`)
-
let default = (props: props) => {
open Markdown
@@ -373,9 +364,9 @@ let default = (props: props) => {
})
let allResources = {
- let npms = props["packages"]->Array.map(pkg => Resource.Npm(pkg))
- let urls = props["urlResources"]->Array.map(res => Resource.Url(res))
- let outdated = props["unmaintained"]->Array.map(pkg => Resource.Outdated(pkg))
+ let npms = props.packages->Array.map(pkg => Resource.Npm(pkg))
+ let urls = props.urlResources->Array.map(res => Resource.Url(res))
+ let outdated = props.unmaintained->Array.map(pkg => Resource.Outdated(pkg))
Belt.Array.concatMany([npms, urls, outdated])
}
@@ -420,7 +411,7 @@ let default = (props: props) => {
})
let onKeywordSelect = keyword => {
- scrollToTop()
+ WebAPI.Window.scrollTo(window, ~options={left: 0.0, top: 0.0, behavior: Smooth})
setState(_ => {
Filtered(keyword)
})
@@ -524,73 +515,99 @@ let default = (props: props) => {
>
}
-type npmData = {
- "objects": array<{
- "searchScore": float,
- "score": {
- "final": float,
- "detail": {"quality": float, "popularity": float, "maintenance": float},
- },
- "package": {
- "name": string,
- "keywords": array,
- "description": option,
- "version": string,
- "links": {"npm": string, "repository": option},
- },
- }>,
-}
-
-module Response = {
- type t
- @send external json: t => promise = "json"
+let parsePkgs = data => {
+ open JSON
+
+ switch data {
+ | Object(dict{"objects": Array(arr)}) =>
+ arr->Array.filterMap(pkg => {
+ switch pkg {
+ | Object(dict{
+ "searchScore": Number(searchScore),
+ "score": Object(dict{"detail": Object(dict{"maintenance": Number(maintenanceScore)})}),
+ "package": Object(dict{
+ "name": String(name),
+ "keywords": Array(keywords),
+ "version": String(version),
+ "description": ?Some(String(description)),
+ "links": Object(dict{
+ "npm": String(npmHref),
+ "repository": ?Some(String(repositoryHref)),
+ }),
+ }),
+ }) =>
+ let keywords =
+ keywords
+ ->Array.filterMap(k => {
+ switch k {
+ | String(k) => Some(k)
+ | _ => None
+ }
+ })
+ ->Resource.filterKeywords
+ ->Resource.uniqueKeywords
+
+ Some({
+ name,
+ version,
+ keywords,
+ description,
+ repositoryHref: repositoryHref->Null.make,
+ npmHref,
+ searchScore,
+ maintenanceScore,
+ })
+ | _ => None
+ }
+ })
+ | _ => []
+ }
}
-@val external fetchNpmPackages: string => promise = "fetch"
-
-let parsePkgs = data =>
- Array.map(data["objects"], item => {
- let pkg = item["package"]
- {
- name: pkg["name"],
- version: pkg["version"],
- keywords: Resource.filterKeywords(pkg["keywords"])->Resource.uniqueKeywords,
- description: Option.getOr(pkg["description"], ""),
- repositoryHref: Null.fromOption(pkg["links"]["repository"]),
- npmHref: pkg["links"]["npm"],
- searchScore: item["searchScore"],
- maintenanceScore: item["score"]["detail"]["maintenance"],
- }
- })
-
let getStaticProps: Next.GetStaticProps.t = async _ctx => {
let baseUrl = "https://registry.npmjs.org/-/v1/search?text=keywords:rescript&size=250&maintenance=1.0&popularity=0.5&quality=0.9"
let (one, two, three) = await Promise.all3((
- fetchNpmPackages(baseUrl),
- fetchNpmPackages(baseUrl ++ "&from=250"),
- fetchNpmPackages(baseUrl ++ "&from=500"),
+ fetch(baseUrl),
+ fetch(baseUrl ++ "&from=250"),
+ fetch(baseUrl ++ "&from=500"),
))
+ let responseToOption = async response => {
+ try {
+ let json = await response->WebAPI.Response.json
+ Some(json)
+ } catch {
+ | _ =>
+ Console.error2("Failed to parse response", response)
+ None
+ }
+ }
+
let (data1, data2, data3) = await Promise.all3((
- one->Response.json,
- two->Response.json,
- three->Response.json,
+ one->responseToOption,
+ two->responseToOption,
+ three->responseToOption,
))
let unmaintained = []
let pkges =
- parsePkgs(data1)
- ->Array.concat(parsePkgs(data2))
- ->Array.concat(parsePkgs(data3))
+ [data1, data2, data3]
+ ->Array.filterMap(d =>
+ switch d {
+ | Some(d) => Some(parsePkgs(d))
+ | None => None
+ }
+ )
+ ->Array.flat
->Array.filter(pkg => {
if packageAllowList->Array.includes(pkg.name) {
true
} else if pkg.name->String.includes("reason") {
false
} else if pkg.maintenanceScore < 0.3 {
- let _ = unmaintained->Array.push(pkg)
+ unmaintained->Array.push(pkg)
false
} else {
true
@@ -606,9 +623,9 @@ let getStaticProps: Next.GetStaticProps.t = async _ctx => {
{
"props": {
- "packages": pkges,
- "unmaintained": unmaintained,
- "urlResources": urlResources,
+ packages: pkges,
+ unmaintained,
+ urlResources,
},
}
}
diff --git a/src/Packages.resi b/src/Packages.resi
index 1c976f951..6f847a819 100644
--- a/src/Packages.resi
+++ b/src/Packages.resi
@@ -18,9 +18,9 @@ type npmPackage = {
}
type props = {
- "packages": array,
- "urlResources": array,
- "unmaintained": array,
+ packages: array,
+ urlResources: array,
+ unmaintained: array,
}
let default: props => React.element
diff --git a/src/Playground.res b/src/Playground.res
index cb640325f..bd20c5939 100644
--- a/src/Playground.res
+++ b/src/Playground.res
@@ -352,30 +352,20 @@ module ResultPane = {
}
module WarningFlagsWidget = {
- @set external _scrollTop: (Dom.element, int) => unit = "scrollTop"
- @send external focus: Dom.element => unit = "focus"
-
- @send external blur: Dom.element => unit = "blur"
-
- @get external scrollHeight: Dom.element => int = "scrollHeight"
- @get external clientHeight: Dom.element => int = "clientHeight"
- @get external scrollTop: Dom.element => int = "scrollTop"
- @get external offsetTop: Dom.element => int = "offsetTop"
- @get external offsetHeight: Dom.element => int = "offsetHeight"
-
- @set external setScrollTop: (Dom.element, int) => unit = "scrollTop"
-
// Inspired by MUI (who got inspired by WAI best practise examples)
// https://github.com/mui-org/material-ui/blob/next/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js#L327
- let scrollToElement = (~parent: Dom.element, element: Dom.element): unit =>
- if parent->scrollHeight > parent->clientHeight {
- let scrollBottom = parent->clientHeight + parent->scrollTop
- let elementBottom = element->offsetTop + element->offsetHeight
+ let scrollToElement = (
+ ~parent: WebAPI.DOMAPI.htmlElement,
+ element: WebAPI.DOMAPI.htmlElement,
+ ): unit =>
+ if parent.scrollHeight > parent.clientHeight {
+ let scrollBottom = parent.clientHeight + Float.toInt(parent.scrollTop)
+ let elementBottom = element.offsetTop + element.offsetHeight
if elementBottom > scrollBottom {
- parent->setScrollTop(elementBottom - parent->clientHeight)
- } else if element->offsetTop - element->offsetHeight < parent->scrollTop {
- parent->setScrollTop(element->offsetTop - element->offsetHeight)
+ parent.scrollTop = Float.fromInt(elementBottom - parent.clientHeight)
+ } else if element.offsetTop - element.offsetHeight < Float.toInt(parent.scrollTop) {
+ parent.scrollTop = Float.fromInt(element.offsetTop - element.offsetHeight)
}
}
@@ -527,9 +517,11 @@ module WarningFlagsWidget = {
// Used for the text input
let inputRef = React.useRef(Nullable.null)
- let focusInput = () => inputRef.current->Nullable.forEach(el => el->focus)
+ let focusInput = () =>
+ inputRef.current->Nullable.forEach(el => WebAPI.HTMLInputElement.focus(el))
- let blurInput = () => inputRef.current->Nullable.forEach(el => el->blur)
+ let blurInput = () =>
+ inputRef.current->Nullable.forEach(el => WebAPI.HTMLInputElement.focus(el))
let chips = Array.mapWithIndex(flags, (token, i) => {
let {WarningFlagDescription.Parser.flag: flag, enabled} = token
@@ -696,7 +688,8 @@ module WarningFlagsWidget = {
let parent = listboxRef.current->Nullable.toOption
switch (parent, el) {
- | (Some(parent), Some(el)) => Some(() => scrollToElement(~parent, el))
+ | (Some(parent), Some(el)) =>
+ Some(() => scrollToElement(~parent, (Obj.magic(el): WebAPI.DOMAPI.htmlElement)))
| _ => None
}
})->Some
@@ -745,7 +738,7 @@ module WarningFlagsWidget = {
let suggestionBox =
Option.map(suggestions, elements =>
>))}
className="p-2 absolute overflow-auto z-50 border-b rounded border-l border-r block w-full bg-gray-100 max-h-[15rem]">
elements
@@ -816,7 +809,7 @@ module WarningFlagsWidget = {
chips
>))}
className="inline-block p-1 max-w-20 outline-none bg-gray-90 placeholder-gray-20 placeholder-opacity-50"
placeholder="Flags"
type_="text"
@@ -1064,7 +1057,7 @@ module ControlPanel = {
let onClick = evt => {
ReactEvent.Mouse.preventDefault(evt)
- let ret = copyToClipboard(Webapi.Window.Location.href)
+ let ret = copyToClipboard(window.location.href)
if ret {
setState(_ => CopySuccess)
}
@@ -1129,12 +1122,12 @@ module ControlPanel = {
}
React.useEffect(() => {
- Webapi.Window.addEventListener("keydown", onKeyDown)
- Some(() => Webapi.Window.removeEventListener("keydown", onKeyDown))
+ WebAPI.Window.addEventListener(window, Keydown, onKeyDown)
+ Some(() => WebAPI.Window.removeEventListener(window, Keydown, onKeyDown))
}, [])
let runButtonText = {
- let userAgent = Webapi.Window.Navigator.userAgent
+ let userAgent = window.navigator.userAgent
let run = "Run"
if userAgent->String.includes("iPhone") || userAgent->String.includes("Android") {
run
@@ -1496,9 +1489,7 @@ let make = (~versions: array) => {
None
}, (compilerState, compilerDispatch))
- let (layout, setLayout) = React.useState(_ =>
- Webapi.Window.innerWidth < breakingPoint ? Column : Row
- )
+ let (layout, setLayout) = React.useState(_ => window.innerWidth < breakingPoint ? Column : Row)
let isDragging = React.useRef(false)
@@ -1510,26 +1501,34 @@ let make = (~versions: array) => {
let subPanelRef = React.useRef(Nullable.null)
let onResize = () => {
- let newLayout = Webapi.Window.innerWidth < breakingPoint ? Column : Row
+ let newLayout = window.innerWidth < breakingPoint ? Column : Row
setLayout(_ => newLayout)
switch panelRef.current->Nullable.toOption {
| Some(element) =>
- let offsetTop = Webapi.Element.getBoundingClientRect(element)["top"]
- Webapi.Element.Style.height(element, `calc(100vh - ${offsetTop->Float.toString}px)`)
+ let offsetTop = WebAPI.Element.getBoundingClientRect(element).top
+ WebAPI.Element.setAttribute(
+ element,
+ ~qualifiedName="style",
+ ~value=`height: calc(100vh - ${offsetTop->Float.toString}px)`,
+ )
| None => ()
}
switch subPanelRef.current->Nullable.toOption {
| Some(element) =>
- let offsetTop = Webapi.Element.getBoundingClientRect(element)["top"]
- Webapi.Element.Style.height(element, `calc(100vh - ${offsetTop->Float.toString}px)`)
+ let offsetTop = WebAPI.Element.getBoundingClientRect(element).top
+ WebAPI.Element.setAttribute(
+ element,
+ ~qualifiedName="style",
+ ~value=`height: calc(100vh - ${offsetTop->Float.toString}px)`,
+ )
| None => ()
}
}
React.useEffect(() => {
- Webapi.Window.addEventListener("resize", onResize)
- Some(() => Webapi.Window.removeEventListener("resize", onResize))
+ WebAPI.Window.addEventListener(window, Resize, onResize)
+ Some(() => WebAPI.Window.removeEventListener(window, Resize, onResize))
}, [])
// To force CodeMirror render scrollbar on first render
@@ -1552,30 +1551,50 @@ let make = (~versions: array) => {
subPanelRef.current->Nullable.toOption,
) {
| (Some(panelElement), Some(leftElement), Some(rightElement), Some(subElement)) =>
- let rectPanel = Webapi.Element.getBoundingClientRect(panelElement)
+ let rectPanel = WebAPI.Element.getBoundingClientRect(panelElement)
// Update OutputPanel height
- let offsetTop = Webapi.Element.getBoundingClientRect(subElement)["top"]
- Webapi.Element.Style.height(subElement, `calc(100vh - ${offsetTop->Float.toString}px)`)
+ let offsetTop = WebAPI.Element.getBoundingClientRect(subElement).top
+ WebAPI.Element.setAttribute(
+ subElement,
+ ~qualifiedName="style",
+ ~value=`height: calc(100vh - ${offsetTop->Float.toString}px)`,
+ )
switch layout {
| Row =>
- let delta = Int.toFloat(position) -. rectPanel["left"]
+ let delta = Int.toFloat(position) -. rectPanel.left
- let leftWidth = delta /. rectPanel["width"] *. 100.0
- let rightWidth = (rectPanel["width"] -. delta) /. rectPanel["width"] *. 100.0
+ let leftWidth = delta /. rectPanel.width *. 100.0
+ let rightWidth = (rectPanel.width -. delta) /. rectPanel.width *. 100.0
- Webapi.Element.Style.width(leftElement, `${leftWidth->Float.toString}%`)
- Webapi.Element.Style.width(rightElement, `${rightWidth->Float.toString}%`)
+ WebAPI.Element.setAttribute(
+ leftElement,
+ ~qualifiedName="style",
+ ~value=`width: ${leftWidth->Float.toString}%`,
+ )
+ WebAPI.Element.setAttribute(
+ rightElement,
+ ~qualifiedName="style",
+ ~value=`width: ${rightWidth->Float.toString}%`,
+ )
| Column =>
- let delta = Int.toFloat(position) -. rectPanel["top"]
+ let delta = Int.toFloat(position) -. rectPanel.top
- let topHeight = delta /. rectPanel["height"] *. 100.
- let bottomHeight = (rectPanel["height"] -. delta) /. rectPanel["height"] *. 100.
+ let topHeight = delta /. rectPanel.height *. 100.
+ let bottomHeight = (rectPanel.height -. delta) /. rectPanel.height *. 100.
- Webapi.Element.Style.height(leftElement, `${topHeight->Float.toString}%`)
- Webapi.Element.Style.height(rightElement, `${bottomHeight->Float.toString}%`)
+ WebAPI.Element.setAttribute(
+ leftElement,
+ ~qualifiedName="style",
+ ~value=`height: ${topHeight->Float.toString}%`,
+ )
+ WebAPI.Element.setAttribute(
+ rightElement,
+ ~qualifiedName="style",
+ ~value=`height: ${bottomHeight->Float.toString}%`,
+ )
}
| _ => ()
}
@@ -1594,15 +1613,15 @@ let make = (~versions: array) => {
onMove(position)
}
- Webapi.Window.addEventListener("mousemove", onMouseMove)
- Webapi.Window.addEventListener("touchmove", onTouchMove)
- Webapi.Window.addEventListener("mouseup", onMouseUp)
+ WebAPI.Window.addEventListener(window, Mousemove, onMouseMove)
+ WebAPI.Window.addEventListener(window, Touchmove, onTouchMove)
+ WebAPI.Window.addEventListener(window, Mouseup, onMouseUp)
Some(
() => {
- Webapi.Window.removeEventListener("mousemove", onMouseMove)
- Webapi.Window.removeEventListener("touchmove", onTouchMove)
- Webapi.Window.removeEventListener("mouseup", onMouseUp)
+ WebAPI.Window.removeEventListener(window, Mousemove, onMouseMove)
+ WebAPI.Window.removeEventListener(window, Touchmove, onTouchMove)
+ WebAPI.Window.removeEventListener(window, Mouseup, onMouseUp)
},
)
}, [layout])
@@ -1765,10 +1784,10 @@ let make = (~versions: array) => {
/>
+ ref={ReactDOM.Ref.domRef((Obj.magic(panelRef): React.ref
>))}>
// Left Panel
>))}
className={`${layout == Column ? "h-2/4" : "!h-full"} ${layout == Column
? "w-full"
: "w-[50%]"}`}>
@@ -1785,10 +1804,10 @@ let make = (~versions: array) => {
| None => ()
| Some(timer) => clearTimeout(timer)
}
- let timer = setTimeout(() => {
+ let timer = setTimeout(~handler=() => {
timeoutCompile.current()
typingTimer.current = None
- }, 100)
+ }, ~timeout=100)
typingTimer.current = Some(timer)
}}
onMarkerFocus={rowCol => setFocusedRowCol(_prev => Some(rowCol))}
@@ -1797,7 +1816,7 @@ let make = (~versions: array) => {
// Separator
>))}
// TODO: touch-none not applied
className={`flex items-center justify-center touch-none select-none bg-gray-70 opacity-30 hover:opacity-50 rounded-lg ${layout ==
Column
@@ -1812,14 +1831,16 @@ let make = (~versions: array) => {
// Right Panel
>))}
className={`${layout == Column ? "h-6/15" : "!h-inherit"} ${layout == Column
? "w-full"
: "w-[50%]"}`}>
{React.array(headers)}
-
+
>))}
+ className="overflow-auto">
diff --git a/src/SyntaxLookup.res b/src/SyntaxLookup.res
index 843cb87af..a9aa4d147 100644
--- a/src/SyntaxLookup.res
+++ b/src/SyntaxLookup.res
@@ -141,10 +141,7 @@ type state =
| ShowFiltered(string, array
) // (search, filteredItems)
| ShowDetails(Item.t)
-@val @scope("window")
-external scrollTo: (int, int) => unit = "scrollTo"
-
-let scrollToTop = () => scrollTo(0, 0)
+let scrollToTop = () => WebAPI.Window.scrollTo(window, ~options={left: 0.0, top: 0.0})
type props = {mdxSources: array}
type params = {slug: string}
diff --git a/src/Try.res b/src/Try.res
index 15fa8f46c..feef200c7 100644
--- a/src/Try.res
+++ b/src/Try.res
@@ -33,10 +33,8 @@ let default = props => {
let getStaticProps: Next.GetStaticProps.t = async _ => {
let versions = {
- let response = await Webapi.Fetch.fetch(
- "https://cdn.rescript-lang.org/playground-bundles/versions.json",
- )
- let json = await Webapi.Fetch.Response.json(response)
+ let response = await fetch("https://cdn.rescript-lang.org/playground-bundles/versions.json")
+ let json = await WebAPI.Response.json(response)
json
->JSON.Decode.array
->Option.getOrThrow
diff --git a/src/bindings/Jsdom.res b/src/bindings/Jsdom.res
index 5021bab42..43f12c740 100644
--- a/src/bindings/Jsdom.res
+++ b/src/bindings/Jsdom.res
@@ -1,5 +1,5 @@
-type window = {document: Dom.document}
-type t = {window: window}
+type window = {document: WebAPI.DOMAPI.document}
+type t = {window: WebAPI.DOMAPI.window}
@module("jsdom") @new
external make: string => t = "JSDOM"
diff --git a/src/bindings/Webapi.res b/src/bindings/Webapi.res
deleted file mode 100644
index ab53ceb41..000000000
--- a/src/bindings/Webapi.res
+++ /dev/null
@@ -1,96 +0,0 @@
-module Document = {
- @val external document: Dom.element = "document"
- @scope("document") @val external createElement: string => Dom.element = "createElement"
- @scope("document") @val external createTextNode: string => Dom.element = "createTextNode"
- @send
- external querySelector: (Dom.document, string) => Nullable.t = "querySelector"
- @send
- external querySelectorAll: (Dom.document, string) => Js.Array2.array_like =
- "querySelectorAll"
-}
-
-module ClassList = {
- type t
- @send external toggle: (t, string) => unit = "toggle"
- @send external remove: (t, string) => unit = "remove"
-}
-
-module Element = {
- @send external appendChild: (Dom.element, Dom.element) => unit = "appendChild"
- @send external removeChild: (Dom.element, Dom.element) => unit = "removeChild"
- @set external setClassName: (Dom.element, string) => unit = "className"
- @get external classList: Dom.element => ClassList.t = "classList"
- @send external getBoundingClientRect: Dom.element => {..} = "getBoundingClientRect"
- @send external addEventListener: (Dom.element, string, unit => unit) => unit = "addEventListener"
- @send external getAttribute: (Dom.element, string) => Nullable.t = "getAttribute"
-
- @send
- external getElementById: (Dom.element, string) => Nullable.t = "getElementById"
-
- type contentWindow
- @get external contentWindow: Dom.element => option = "contentWindow"
-
- @send
- external postMessage: (contentWindow, string, ~targetOrigin: string=?) => unit = "postMessage"
-
- @send
- external postMessageAny: (contentWindow, 'a, ~targetOrigin: string=?) => unit = "postMessage"
-
- module Style = {
- @scope("style") @set external width: (Dom.element, string) => unit = "width"
- @scope("style") @set external height: (Dom.element, string) => unit = "height"
- }
-}
-
-type animationFrameId
-
-@scope("window") @val
-external requestAnimationFrame: (unit => unit) => animationFrameId = "requestAnimationFrame"
-
-@scope("window") @val
-external cancelAnimationFrame: animationFrameId => unit = "cancelAnimationFrame"
-
-module Window = {
- @scope("window") @val external addEventListener: (string, 'a => unit) => unit = "addEventListener"
- @scope("window") @val
- external removeEventListener: (string, 'a => unit) => unit = "removeEventListener"
- @scope("window") @val external innerWidth: int = "innerWidth"
- @scope("window") @val external innerHeight: int = "innerHeight"
- @scope("window") @val external scrollY: int = "scrollY"
-
- module History = {
- @scope(("window", "history")) @val
- external pushState: (nullable<'a>, @as(json`""`) _, ~url: string=?) => unit = "pushState"
- @scope(("window", "history")) @val
- external replaceState: (nullable<'a>, @as(json`""`) _, ~url: string=?) => unit = "replaceState"
- }
-
- module Location = {
- @scope(("window", "location")) @val external href: string = "href"
- }
-
- module Navigator = {
- @scope(("window", "navigator")) @val external userAgent: string = "userAgent"
- }
-}
-
-module Fetch = {
- module Response = {
- type t
- @send external text: t => promise = "text"
- @send external json: t => promise = "json"
- }
-
- @val external fetch: string => promise = "fetch"
-}
-
-module URL = {
- type t = {
- hash: string,
- host: string,
- hostname: string,
- href: string,
- pathname: string,
- }
- @new external make: string => t = "URL"
-}
diff --git a/src/common/CompilerManagerHook.res b/src/common/CompilerManagerHook.res
index 2d22a43e9..e17b92bac 100644
--- a/src/common/CompilerManagerHook.res
+++ b/src/common/CompilerManagerHook.res
@@ -583,7 +583,7 @@ let useCompilerManager = (
| SetupFailed(_) => ()
| Ready(ready) =>
let url = createUrl(router.route, ready)
- Webapi.Window.History.replaceState(null, ~url)
+ WebAPI.History.replaceState(history, ~data=JSON.Null, ~unused="", ~url)
}
}
diff --git a/src/common/EvalIFrame.res b/src/common/EvalIFrame.res
index 507268f66..3531edcf1 100644
--- a/src/common/EvalIFrame.res
+++ b/src/common/EvalIFrame.res
@@ -69,23 +69,24 @@ let srcDoc = `