Skip to content

Commit 01978a0

Browse files
committed
more changes
1 parent 93c20e0 commit 01978a0

File tree

8 files changed

+280
-283
lines changed

8 files changed

+280
-283
lines changed

src/Packages.res

Lines changed: 91 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ module Resource = {
7373
})
7474
}
7575

76-
let uniqueKeywords: array<string> => array<string> = %raw(`(keywords) => [...new Set(keywords)]`)
76+
let uniqueKeywords = arr => arr->Set.fromArray->Set.toArray
7777

7878
let isOfficial = (res: t) => {
7979
switch res {
@@ -340,24 +340,15 @@ module InfoSidebar = {
340340
}
341341

342342
type props = {
343-
"packages": array<npmPackage>,
344-
"urlResources": array<urlResource>,
345-
"unmaintained": array<npmPackage>,
343+
packages: array<npmPackage>,
344+
urlResources: array<urlResource>,
345+
unmaintained: array<npmPackage>,
346346
}
347347

348348
type state =
349349
| All
350350
| Filtered(string) // search term
351351

352-
let scrollToTop: unit => unit = %raw(`function() {
353-
window.scroll({
354-
top: 0,
355-
left: 0,
356-
behavior: 'smooth'
357-
});
358-
}
359-
`)
360-
361352
let default = (props: props) => {
362353
open Markdown
363354

@@ -373,9 +364,9 @@ let default = (props: props) => {
373364
})
374365

375366
let allResources = {
376-
let npms = props["packages"]->Array.map(pkg => Resource.Npm(pkg))
377-
let urls = props["urlResources"]->Array.map(res => Resource.Url(res))
378-
let outdated = props["unmaintained"]->Array.map(pkg => Resource.Outdated(pkg))
367+
let npms = props.packages->Array.map(pkg => Resource.Npm(pkg))
368+
let urls = props.urlResources->Array.map(res => Resource.Url(res))
369+
let outdated = props.unmaintained->Array.map(pkg => Resource.Outdated(pkg))
379370
Belt.Array.concatMany([npms, urls, outdated])
380371
}
381372

@@ -420,7 +411,7 @@ let default = (props: props) => {
420411
})
421412

422413
let onKeywordSelect = keyword => {
423-
scrollToTop()
414+
WebAPI.Window.scrollTo(window, ~options={left: 0.0, top: 0.0, behavior: Smooth})
424415
setState(_ => {
425416
Filtered(keyword)
426417
})
@@ -524,73 +515,107 @@ let default = (props: props) => {
524515
</>
525516
}
526517

527-
type npmData = {
528-
"objects": array<{
529-
"searchScore": float,
530-
"score": {
531-
"final": float,
532-
"detail": {"quality": float, "popularity": float, "maintenance": float},
533-
},
534-
"package": {
535-
"name": string,
536-
"keywords": array<string>,
537-
"description": option<string>,
538-
"version": string,
539-
"links": {"npm": string, "repository": option<string>},
540-
},
541-
}>,
542-
}
518+
let parsePkgs = data => {
519+
open JSON
520+
521+
switch data {
522+
| Object(dict{"objects": Array(arr)}) =>
523+
arr->Array.filterMap(pkg => {
524+
switch pkg {
525+
| Object(dict{
526+
"searchScore": Number(searchScore),
527+
"score": Object(dict{"detail": Object(dict{"maintenance": Number(maintenanceScore)})}),
528+
"package": Object(
529+
dict{
530+
"name": String(name),
531+
"keywords": Array(keywords),
532+
"version": String(version),
533+
"links": Object(dict{"npm": String(npmHref)} as links),
534+
} as package,
535+
),
536+
}) =>
537+
let keywords =
538+
keywords
539+
->Array.filterMap(k => {
540+
switch k {
541+
| String(k) => Some(k)
542+
| _ => None
543+
}
544+
})
545+
->Resource.filterKeywords
546+
->Resource.uniqueKeywords
543547

544-
module Response = {
545-
type t
546-
@send external json: t => promise<npmData> = "json"
547-
}
548+
let repositoryHref = switch links->Dict.get("repository") {
549+
| Some(String(v)) => Null.Value(v)
550+
| _ => Null
551+
}
548552

549-
@val external fetchNpmPackages: string => promise<Response.t> = "fetch"
550-
551-
let parsePkgs = data =>
552-
Array.map(data["objects"], item => {
553-
let pkg = item["package"]
554-
{
555-
name: pkg["name"],
556-
version: pkg["version"],
557-
keywords: Resource.filterKeywords(pkg["keywords"])->Resource.uniqueKeywords,
558-
description: Option.getOr(pkg["description"], ""),
559-
repositoryHref: Null.fromOption(pkg["links"]["repository"]),
560-
npmHref: pkg["links"]["npm"],
561-
searchScore: item["searchScore"],
562-
maintenanceScore: item["score"]["detail"]["maintenance"],
563-
}
564-
})
553+
let description = switch package {
554+
| dict{"description": String(description)} => description
555+
| _ => ""
556+
}
557+
558+
Some({
559+
name,
560+
version,
561+
keywords,
562+
description,
563+
repositoryHref,
564+
npmHref,
565+
searchScore,
566+
maintenanceScore,
567+
})
568+
| _ => None
569+
}
570+
})
571+
| _ => []
572+
}
573+
}
565574

566575
let getStaticProps: Next.GetStaticProps.t<props, unit> = async _ctx => {
567576
let baseUrl = "https://registry.npmjs.org/-/v1/search?text=keywords:rescript&size=250&maintenance=1.0&popularity=0.5&quality=0.9"
568577

569578
let (one, two, three) = await Promise.all3((
570-
fetchNpmPackages(baseUrl),
571-
fetchNpmPackages(baseUrl ++ "&from=250"),
572-
fetchNpmPackages(baseUrl ++ "&from=500"),
579+
fetch(baseUrl),
580+
fetch(baseUrl ++ "&from=250"),
581+
fetch(baseUrl ++ "&from=500"),
573582
))
574583

584+
let responseToOption = async response => {
585+
try {
586+
let json = await response->WebAPI.Response.json
587+
Some(json)
588+
} catch {
589+
| _ =>
590+
Console.error2("Failed to parse response", response)
591+
None
592+
}
593+
}
594+
575595
let (data1, data2, data3) = await Promise.all3((
576-
one->Response.json,
577-
two->Response.json,
578-
three->Response.json,
596+
one->responseToOption,
597+
two->responseToOption,
598+
three->responseToOption,
579599
))
580600

581601
let unmaintained = []
582602

583603
let pkges =
584-
parsePkgs(data1)
585-
->Array.concat(parsePkgs(data2))
586-
->Array.concat(parsePkgs(data3))
604+
[data1, data2, data3]
605+
->Array.filterMap(d =>
606+
switch d {
607+
| Some(d) => Some(parsePkgs(d))
608+
| None => None
609+
}
610+
)
611+
->Array.flat
587612
->Array.filter(pkg => {
588613
if packageAllowList->Array.includes(pkg.name) {
589614
true
590615
} else if pkg.name->String.includes("reason") {
591616
false
592617
} else if pkg.maintenanceScore < 0.3 {
593-
let _ = unmaintained->Array.push(pkg)
618+
unmaintained->Array.push(pkg)
594619
false
595620
} else {
596621
true
@@ -606,9 +631,9 @@ let getStaticProps: Next.GetStaticProps.t<props, unit> = async _ctx => {
606631

607632
{
608633
"props": {
609-
"packages": pkges,
610-
"unmaintained": unmaintained,
611-
"urlResources": urlResources,
634+
packages: pkges,
635+
unmaintained,
636+
urlResources,
612637
},
613638
}
614639
}

src/Packages.resi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ type npmPackage = {
1818
}
1919

2020
type props = {
21-
"packages": array<npmPackage>,
22-
"urlResources": array<urlResource>,
23-
"unmaintained": array<npmPackage>,
21+
packages: array<npmPackage>,
22+
urlResources: array<urlResource>,
23+
unmaintained: array<npmPackage>,
2424
}
2525

2626
let default: props => React.element

src/Playground.res

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -352,30 +352,20 @@ module ResultPane = {
352352
}
353353

354354
module WarningFlagsWidget = {
355-
@set external _scrollTop: (Dom.element, int) => unit = "scrollTop"
356-
@send external focus: Dom.element => unit = "focus"
357-
358-
@send external blur: Dom.element => unit = "blur"
359-
360-
@get external scrollHeight: Dom.element => int = "scrollHeight"
361-
@get external clientHeight: Dom.element => int = "clientHeight"
362-
@get external scrollTop: Dom.element => int = "scrollTop"
363-
@get external offsetTop: Dom.element => int = "offsetTop"
364-
@get external offsetHeight: Dom.element => int = "offsetHeight"
365-
366-
@set external setScrollTop: (Dom.element, int) => unit = "scrollTop"
367-
368355
// Inspired by MUI (who got inspired by WAI best practise examples)
369356
// https://github.com/mui-org/material-ui/blob/next/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js#L327
370-
let scrollToElement = (~parent: Dom.element, element: Dom.element): unit =>
371-
if parent->scrollHeight > parent->clientHeight {
372-
let scrollBottom = parent->clientHeight + parent->scrollTop
373-
let elementBottom = element->offsetTop + element->offsetHeight
357+
let scrollToElement = (
358+
~parent: WebAPI.DOMAPI.htmlElement,
359+
element: WebAPI.DOMAPI.htmlElement,
360+
): unit =>
361+
if parent.scrollHeight > parent.clientHeight {
362+
let scrollBottom = parent.clientHeight + Float.toInt(parent.scrollTop)
363+
let elementBottom = element.offsetTop + element.offsetHeight
374364

375365
if elementBottom > scrollBottom {
376-
parent->setScrollTop(elementBottom - parent->clientHeight)
377-
} else if element->offsetTop - element->offsetHeight < parent->scrollTop {
378-
parent->setScrollTop(element->offsetTop - element->offsetHeight)
366+
parent.scrollTop = Float.fromInt(elementBottom - parent.clientHeight)
367+
} else if element.offsetTop - element.offsetHeight < Float.toInt(parent.scrollTop) {
368+
parent.scrollTop = Float.fromInt(element.offsetTop - element.offsetHeight)
379369
}
380370
}
381371

@@ -525,11 +515,15 @@ module WarningFlagsWidget = {
525515
let listboxRef = React.useRef(Nullable.null)
526516

527517
// Used for the text input
528-
let inputRef = React.useRef(Nullable.null)
518+
let inputRef: React.ref<Nullable.t<WebAPI.DOMAPI.htmlInputElement>> = React.useRef(
519+
Nullable.null,
520+
)
529521

530-
let focusInput = () => inputRef.current->Nullable.forEach(el => el->focus)
522+
let focusInput = () =>
523+
inputRef.current->Nullable.forEach(el => WebAPI.HTMLInputElement.focus(el))
531524

532-
let blurInput = () => inputRef.current->Nullable.forEach(el => el->blur)
525+
let blurInput = () =>
526+
inputRef.current->Nullable.forEach(el => WebAPI.HTMLInputElement.focus(el))
533527

534528
let chips = Array.mapWithIndex(flags, (token, i) => {
535529
let {WarningFlagDescription.Parser.flag: flag, enabled} = token
@@ -696,7 +690,8 @@ module WarningFlagsWidget = {
696690
let parent = listboxRef.current->Nullable.toOption
697691

698692
switch (parent, el) {
699-
| (Some(parent), Some(el)) => Some(() => scrollToElement(~parent, el))
693+
| (Some(parent), Some(el)) =>
694+
Some(() => scrollToElement(~parent, (Obj.magic(el): WebAPI.DOMAPI.htmlElement)))
700695
| _ => None
701696
}
702697
})->Some
@@ -745,7 +740,7 @@ module WarningFlagsWidget = {
745740
let suggestionBox =
746741
Option.map(suggestions, elements =>
747742
<div
748-
ref={ReactDOM.Ref.domRef(listboxRef)}
743+
ref={ReactDOM.Ref.domRef((Obj.magic(listboxRef): React.ref<Nullable.t<Dom.element>>))}
749744
className="p-2 absolute overflow-auto z-50 border-b rounded border-l border-r block w-full bg-gray-100 max-h-[15rem]">
750745
elements
751746
</div>
@@ -816,7 +811,7 @@ module WarningFlagsWidget = {
816811
chips
817812
<section className="mt-3">
818813
<input
819-
ref={ReactDOM.Ref.domRef(inputRef)}
814+
ref={ReactDOM.Ref.domRef((Obj.magic(inputRef): React.ref<Nullable.t<Dom.element>>))}
820815
className="inline-block p-1 max-w-20 outline-none bg-gray-90 placeholder-gray-20 placeholder-opacity-50"
821816
placeholder="Flags"
822817
type_="text"
@@ -1791,7 +1786,7 @@ let make = (~versions: array<string>) => {
17911786
/>
17921787
<div
17931788
className={`flex ${layout == Column ? "flex-col" : "flex-row"}`}
1794-
ref={ReactDOM.Ref.domRef(panelRef->Obj.magic)}>
1789+
ref={ReactDOM.Ref.domRef((Obj.magic(panelRef): React.ref<Nullable.t<Dom.element>>))}>
17951790
// Left Panel
17961791
<div
17971792
ref={ReactDOM.Ref.domRef((Obj.magic(leftPanelRef): React.ref<Nullable.t<Dom.element>>))}
@@ -1838,7 +1833,7 @@ let make = (~versions: array<string>) => {
18381833
</div>
18391834
// Right Panel
18401835
<div
1841-
ref={ReactDOM.Ref.domRef(rightPanelRef->Obj.magic)}
1836+
ref={ReactDOM.Ref.domRef((Obj.magic(rightPanelRef): React.ref<Nullable.t<Dom.element>>))}
18421837
className={`${layout == Column ? "h-6/15" : "!h-inherit"} ${layout == Column
18431838
? "w-full"
18441839
: "w-[50%]"}`}>

src/SyntaxLookup.res

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,7 @@ type state =
141141
| ShowFiltered(string, array<Item.t>) // (search, filteredItems)
142142
| ShowDetails(Item.t)
143143

144-
@val @scope("window")
145-
external scrollTo: (int, int) => unit = "scrollTo"
146-
147-
let scrollToTop = () => scrollTo(0, 0)
144+
let scrollToTop = () => WebAPI.Window.scrollTo(window, ~options={left: 0.0, top: 0.0})
148145

149146
type props = {mdxSources: array<MdxRemote.output>}
150147
type params = {slug: string}

0 commit comments

Comments
 (0)