Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/content/docs/api-surface.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ let redirect = WebAPI.Response.redirect(~url="/login", ~status=302)
## DOM

DOM values are operated on through public interface modules.
`WebAPI.Element` is the method module for element values. When you need to name the element type explicitly, use `WebAPI.DOM.element`; most examples can rely on inference from `Document.createElement`, `Document.querySelector`, and related DOM helpers.

```ReScript
let document = WebAPI.Window.current->WebAPI.Window.document
Expand All @@ -262,8 +263,8 @@ switch maybeButton {
Use conversion helpers when moving between related DOM interface types.

```ReScript
let element = document->WebAPI.Document.createElement("div")
let node = element->WebAPI.Element.asNode
let element: WebAPI.DOM.element = document->WebAPI.Document.createElement("div")
let node: WebAPI.DOM.node = element->WebAPI.Element.asNode
```

## Visual Viewport
Expand Down
8 changes: 3 additions & 5 deletions docs/content/docs/contributing/api-module-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,11 @@ type rec node = {
// ... more properties
}

and element = {
// duplicated property from node
nodeName: string
// ... more properties
}
and element = Base.element
```

For shared DOM base interfaces such as `Element`, the structural record can live in a Base-owned module such as `Base__Element.res`. The DOM API module then keeps the familiar `DOM.element` alias while method modules use `DomTypes.element`.

## Auxiliary Types

Auxiliary types are used to represent types that are not directly related to the Web API but are used in the bindings.
Expand Down
27 changes: 27 additions & 0 deletions docs/content/docs/contributing/module-type-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,30 @@ external checkValidity: htmlButtonElement => bool = "checkValidity"
`;

<Code code={buttonModule} title="DOMAPI/HTMLButtonElement.res" lang="ReScript"></Code>

## Shared element base

`Element.res` is a method module. It does not define the `element` record type directly. The shared DOM element type is owned by Base and threaded back into DOM through aliases:

```ReScript
// Base.res
type element = Base__Element.element

// DomTypes.res
type element = Base.element

// Element.res
include Impl({type t = DomTypes.element})
```

This keeps `Element.Impl` reusable for element subtypes while giving the package one shared base element type. Subtype modules should continue to include the nearest base method implementation:

```ReScript
// HTMLElement.res
include Element.Impl({type t = DomTypes.htmlElement})

// HTMLButtonElement.res
include HTMLElement.Impl({type t = DomTypes.htmlButtonElement})
```

Use `asElement` when a subtype needs to be passed to a function that expects the shared element type.
9 changes: 6 additions & 3 deletions docs/content/docs/philosophy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ The bindings are exposed under the `WebAPI` namespace with the same flat module
```ReScript
open WebAPI.DOM

let myElement: WebAPI.Element.t = document->WebAPI.Document.createElement("div")
let myElement: WebAPI.DOM.element = document->WebAPI.Document.createElement("div")
let id = myElement.id
```

## Interfaces
Expand All @@ -34,6 +35,8 @@ Methods are modeled as functions in a separate module. The idea is that these wi

Inherited methods are duplicated in the inheriting module to eliminate the need to cast the type to the base type.

For DOM elements, `WebAPI.Element` is the method module. The element type itself is exposed as `WebAPI.DOM.element`. Most code does not need to annotate the type because functions such as `Document.createElement` and `Document.querySelector` already return it.

### Overloads

JavaScript supports function overloads, where a function can have multiple signatures. In ReScript, this is not possible, and a method can have multiple bindings with slightly different names. By entering the correct name, tooling should detect all variations of the method.
Expand All @@ -45,8 +48,8 @@ In some cases, type conversion will be required. Subtypes can safely be cast to
```ReScript
open WebAPI.DOM

let element: WebAPI.Element.t = document->WebAPI.Document.createElement("div")
let node: WebAPI.Node.t = element->WebAPI.Element.asNode
let element: WebAPI.DOM.element = document->WebAPI.Document.createElement("div")
let node: WebAPI.DOM.node = element->WebAPI.Element.asNode
```

Any other conversions should be treated as unsafe casts and used with caution, because the type system cannot guarantee they are valid at runtime.
6 changes: 3 additions & 3 deletions docs/superpowers/specs/2026-04-22-unmonorepo-webapi-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Example:

```json
{
"dependencies": ["@plain/dep", { "name": "@other/heavy", "features": ["WebAPI.WebCrypto"] }]
"dependencies": ["@plain/dep", { "name": "@other/heavy", "features": ["WebAPI.Crypto"] }]
}
```

Expand All @@ -114,7 +114,7 @@ The build remains feature-oriented:
- `WebAPI.Base`
- `WebAPI.DOM`
- `WebAPI.Fetch`
- `WebAPI.WebCrypto`
- `WebAPI.Crypto`
- and the rest of the former package surfaces

The unified build keeps the original flat module surface instead of adding generated feature entry modules. For example, consumers should use modules such as:
Expand All @@ -124,7 +124,7 @@ The unified build keeps the original flat module surface instead of adding gener
- `WebAPI.Headers`
- `WebAPI.URL`

Shared DOM base types should be owned by `DOM`, so common references stay short, for example `DOM.element` instead of `BaseDOM.element` or `Base.DOM.element`.
Shared DOM base types can be owned by `Base` when they are needed across feature boundaries, while `DOM` can keep short public aliases such as `DOM.element`. For example, `Base__Element.element` is exposed through `Base.element`, then reused as `DomTypes.element` and `DOM.element`.

## Internal Module Naming

Expand Down
Loading
Loading