Code Monkey home page Code Monkey logo

fable-browser's Introduction

fable-browser

Fable bindings for Browser Web APIs

NuGet Name Description
Nuget Package Fable.Browser.Blob Bindings for the browser Blob API.
Nuget Package Fable.Browser.Dom Bindings for DOM and HTML interfaces
Nuget Package Fable.Browser.Event Bindings for the browser Event interface
Nuget Package Fable.Browser.Performance Bindings for the browser Performance API
Nuget Package Fable.Browser.Url Bindings for the browser Url API
Nuget Package Fable.Browser.WebSocket Bindings for the browser WebSocket API
Nuget Package Fable.Browser.WebRTC Bindings for the browser WebRTC API
Nuget Package Fable.Browser.WebStorage Bindings for the Web Storage API
Nuget Package Fable.Browser.XMLHttpRequest Bindings for the browser XMLHttpRequest API
Nuget Package Fable.Browser.Svg Bindings for the browser Svg API
Nuget Package Fable.Browser.Css Bindings for the browser Css API
Nuget Package Fable.Browser.Worker Bindings for the browser Worker API
Nuget Package Fable.Browser.Geolocation Bindings for the browser Geolocation API
Nuget Package Fable.Browser.Navigator Bindings for the browser Navigator API
Nuget Package Fable.Browser.MediaStream Bindings for the browser MediaStream API
Nuget Package Fable.Browser.MediaRecorder Bindings for the browser MediaRecorder API
Nuget Package Fable.Browser.MediaQueryList Bindings for the browser MediaQueryList API
Nuget Package Fable.Browser.WebGL Bindings for the browser WebGL API
Nuget Package Fable.Browser.IntersectionObserver Bindings for the browser Intersection Observer API
Nuget Package Fable.Browser.ResizeObserver Bindings for the browser Resize Observer API
Nuget Package Fable.Browser.IndexedDB Bindings for the browser IndexedDB API

Usage

After installing one of the Nuget packages you can access the API. For that, you only need to open the Browser namespace.

open Browser

let fooEl = document.getElementById("foo")

Note the API values are actually contained in an [<AutoOpen>] module, so if you need to fully qualify the value to avoid name conflicts, use the full module name (same as the Nuget package without Fable. prefix):

let fooEl = Browser.Dom.document.getElementById("foo")

If you need to reference one of the types in the package, open the Browser.Types namespace:

open Browser.Types

let handleClick (ev: MouseEvent) = printfn "click!"

Publishing

If you have rights to publish the packages, the only thing you need to do is to bump the version in the appropriate RELEASE_NOTES file and then run npm run publish. The build script will automatically detect what packages have new versions, update the .fsproj file and push a release. Just make sure:

  • Your Nuget API key is in a FABLE_NUGET_KEY environmental variable
  • The packages you want to publish are listed in the packages list of the Build.fsx script

fable-browser's People

Contributors

alfonsogarciacaro avatar angelmunoz avatar aronerben avatar baronfel avatar belka-ew avatar bjorn-einar-bjartnes-4ss avatar chkn avatar davedawkins avatar dependabot[bot] avatar dredgy avatar gabrieldavid98 avatar happypig375 avatar ianmanske avatar jirkacv avatar jwosty avatar kentcb avatar kerams avatar kodfodrasz avatar luiz-monad avatar mangelmaxime avatar mangelmaximeas avatar markpattison avatar nhowka avatar nojaf avatar rastreus avatar robitar avatar sumeetdas avatar titaye avatar vbfox avatar zaid-ajaj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

fable-browser's Issues

Binding for `getComputedStyle` should be on `window` not on `document`?

Apparently, it is part of window not part of document? See
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

type Document with
/// Retrieves a collection of styleSheet objects representing the style sheets that correspond to each instance of a link or style object in the document.
[<Emit("$0.styleSheets{{=$1}}")>]
member __.styleSheets with get(): StyleSheetList = jsNative and set(v: StyleSheetList) = jsNative
[<Emit("$0.styleMedia{{=$1}}")>]
member __.styleMedia with get(): StyleMedia = jsNative and set(v: StyleMedia) = jsNative
[<Emit("$0.getComputedStyle($1...)")>]
member __.getComputedStyle(elt: Element, ?pseudoElt: string): CSSStyleDeclaration = jsNative
[<Emit("$0.getMatchedCSSRules($1...)")>]
member __.getMatchedCSSRules(elt: Element, ?pseudoElt: string): CSSRuleList = jsNative

MediaRecorder start should allow passing an argument

abstract start: unit -> unit

If MediaRecorder.start is called without a parameter, then no ondataavailable events will be fired during recording (you only get all data at a time once you stop recording, but not during recording).

Please add a version of start that also accepts a parameter.

See https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/start#syntax for reference.

Use classes for the bindings?

So far we (I) have been recommending interfaces to write bindings, but in recent discussions we are considering the possibility of using classes instead. Some links:

fsharp/fslang-suggestions#1054
fable-compiler/Fable#2353
fable-compiler/Fable#2492

So I'm toying now with the idea of writing a script to automatically convert some of the bindings in this repo to classes to see how far we can go, and if the ergonomics is good enough to start recommending writing classes instead of interfaces (and whether we should change ts2fable).

Merits:

  • We could use normal constructors (we would still leave the static Create method to avoid breaking changes)
  • We could do type testing

Demerits:

  • Namespaces could be a breaking change. We currently have Browser.Types and Browser for the values exposing the changes. But in many cases we wouldn't need
  • Multiple inheritance: many interfaces inherit from more than one interface. Given that JS doesn't allow multiple inheritance either, my hope is that those cases always correspond to actual interfaces. But this mean we will have to review manually multiple cases to see if they can become a class or not.
  • Virtual methods: I think there's no need to inherit and override a method of any type in this repo (mainly because it's not possible right now and we didn't have complaints, although writing raw web components do require this) but if it does become necessary we need to identify the methods and use the verbose F# syntax for virtual declaration (abstract signature plus default declaration with dummy implementation).

Thoughts? cc @MangelMaxime @Zaid-Ajaj @inosik @Booksbaum

Contributing bindings for ResizeObserver

I'm assuming they don't exist yet, or at least I couldn't find them, so I've set up some bindings. Thankfully, they are almost identical to IntersectionObserver, so it should be quite consistent.

It seems like a good opportunity to make a first contribution! Should I just open a pull request? Are there any steps to take?

addEventListener_xyz seems to be missing

The new api seems to only have one addEventListener(string, Event->unit).

The old api had this generic method, and other specialised ones like addEventListener_click(MouseEvent->unit).

This was really nice because you didn't have any magic strings, and you had a bit more type safety because the handler got a MouseEvent, not just a generic Event.

Were these removed on purpose? Is there a chance to add them back?

nextElementSibling and previousElementSibling Not implemented

Description

On elements, nextElementSibling and previousElementSibling do not seem to be defined.

Repro code

https://fable.io/repl/#?code=LYewJgrgNgpgBAUVsGA7ALgKEyADmuAZQE8BndGYHfVOAIQCcQB3UmBgOgBVj9TqCAMQCGAI1gcAwiAYwBtRizacAIiCp4Ci1uymlSCAB4VUpAJYhT8uIMIALYQ1xSZc7LHRwYyNJ4C8cGAgAMYQKBgcAI4Q7MSE3jDB6DJwAES4qZjBlqQgElAgAOYAFAnh6ByoMMZIlL6EZuJmqIUAlEA&html=DwBwfMD04LAFDAM4gIYDsKWesQ&css=Q

Expected and actual results

When given a Node, .nextElementSibling should return the next sibling that is also an element. Same with previousElementSibling

CustomEvent is not generic

The current CustomEvent is not generic which is differs from typescript definition

interface CustomEvent<T = any> extends EventInit {
    detail?: T;
}

vs

type [<AllowNullLiteral>] CustomEvent =
    inherit Event
    abstract detail: obj

I'm not sure how breaking can be to make it to be generic as well

type [<AllowNullLiteral>] CustomEvent<'T> =
    inherit Event
    abstract detail: 'T

if this is an acceptable change I can make a PR

Missing bindings for WebSockets and DataView

Hi,

I have started playing (again) with Fable.
Among other things, I want, this time to experiment with WebSockets . As I want to read binary from it I also want to use DataView.

It may be me, but I did not manage to find bindings for those types.

Thanks to Fable I was able to use an weakly typed escape hatch to get my stuff working, but it would be better, imho, that we have support for those APIs out of the box.

What is your opinion on the matter?

Regards

Use more `option` types in the bindings?

Is there any reason why functions which can return null in JS (e.g. document.querySelector) are not typed as returning option values? With the current types it's trivial to get runtime errors which I wouldn't expect from a statically typed language that compiles to JS. In TypeScript that function returns Element | null which means the user cannot call methods on it without checking that it's not null. In OCaml (BuckleScript) it returns Dom.element option. I would expect the same in F#.

cc @nojaf who suggested I open an issue here

Naming (is hard)

Following discussion from elmish/react#34 (comment)

Another question about the naming is: is there any benefits for adding Fable. to the namespace ? If we want something simple I would name the package Fable.Browser and have the top module be Browser.

I think this makes sense, we can start the names of packages in this repository with Fable.Browser. but the namespace only with Browser..

Other questions:

  • Put interfaces always directly in the Browser namespace? This can be done no matter the name of the package, and there shouldn't be name conflicts. The exceptions could be specialized interfaces that we don't want to open by default (e.g. workers).
  • Values need to be in a module, but should we AutoOpen them (except for workers)? This way the name of the module/package (Dom, Svg, File, Clipboard, WebSocket) is not very important, because just by opening or qualifying Browser users will already have access to global values.
  • Move Console to its own package. MDN includes Window in the DOM Api so it should be ok to keep it here. But moving Console to a different package, we could add it as a dependency in the WebWorker package without having to depend on the rest of the DOM interfaces.

In principle, Node has its own Console object so we shouldn't need to worry about that, but if we put Console in a non-browser package (outside of this repository) we could share it with the next Node bindings too. Although in that case, I'm not sure what namespace we should use for Console ๐Ÿค”

PermissionDescriptor throws `error FABLE: Cannot find Browser.Types.PermissionDescriptor constructor`

When trying to use a navigator.permissions.query({ name = PermissionName.ClipboardRead; userVisibleOnly = false; sysex = false }) I got following error:

 error FABLE: Cannot find Browser.Types.PermissionDescriptor constructor

It seems that generated javascript looks like this:

navigator.permissions.query(new null("clipboard-read", false, false));

But when I try to use it from Fable.io it seems that the proper javascript was generated:

import { Record } from "fable-library/Types.js";
import { record_type, bool_type, string_type } from "fable-library/Reflection.js";

export class PermissionDescriptor extends Record {
    constructor(name, userVisibleOnly, sysex) {
        super();
        this.name = name;
        this.userVisibleOnly = userVisibleOnly;
        this.sysex = sysex;
    }
}

export function PermissionDescriptor$reflection() {
    return record_type("Test.PermissionDescriptor", [], PermissionDescriptor, () => [["name", string_type], ["userVisibleOnly", bool_type], ["sysex", bool_type]]);
}

export const d = navigator.permissions.query(new PermissionDescriptor("clipboard-read", true, true));

I'm using Fable 3.1.15. Maybe the PermissionDescriptor should be defined in a different way?

Here is how the definition looks like in libdom.d.ts:

interface PermissionDescriptor {
    name: PermissionName;
}

New overloads to addEventListener and removeEventListener breaks Fable compilation

It looks like this change is breaking all Fable builds that use addEventListener without an optional parameter.

See this issue for an example.

I'd recommend just removing these overloads:

abstract addEventListener: ``type``: string * listener: (Event->unit) * ?useCapture: bool -> unit
abstract removeEventListener: ``type``: string * listener: (Event->unit) * ?useCapture: bool -> unit

I doubt anyone is really even using that optional parameter, but if that's a concern all options could be made explicit:

type [<AllowNullLiteral>] EventTarget =
    abstract addEventListener: ``type``: string * listener: (Event->unit) -> unit
    abstract addEventListener: ``type``: string * listener: (Event->unit) * useCapture: bool -> unit
    abstract addEventListener: ``type``: string * listener: (Event->unit) * options: AddEventListenerOptions -> unit
    abstract dispatchEvent: evt: Event -> bool
    abstract removeEventListener: ``type``: string * listener: (Event->unit) * -> unit
    abstract removeEventListener: ``type``: string * listener: (Event->unit) * useCapture: bool -> unit
    abstract removeEventListener: ``type``: string * listener: (Event->unit) * options: RemoveEventListenerOptions -> unit

API generates invalid IL

See dotnet/linker#2281 (comment)

The following code in Browser.Dom.fs generates invalid IL:

type [<AllowNullLiteral>] GlobalEventHandlers =
    abstract onpointercancel: (PointerEvent -> 'Out) with get, set
    abstract onpointerdown: (PointerEvent -> 'Out) with get, set
    abstract onpointerenter: (PointerEvent -> 'Out) with get, set
    abstract onpointerleave: (PointerEvent -> 'Out) with get, set
    abstract onpointermove: (PointerEvent -> 'Out) with get, set
    abstract onpointerout: (PointerEvent -> 'Out) with get, set
    abstract onpointerover: (PointerEvent -> 'Out) with get, set
    abstract onpointerup: (PointerEvent -> 'Out) with get, set
    abstract onwheel: (WheelEvent -> 'Out) with get, set

In this context, the type parameter 'Out is meaningless. This is not supposed to be valid F#; the compiler is only allowing it due to a bug. When this gets fixed in FCS, this code (and any other code like it) will generate compiler errors.

Missing FormData.create() call?

I may have missed something but it looks like the bindings in this repo only define the inteface for FormData and FormDataType but provide no implementation. Fable.SimpleHttp contains the following snippet:

[<Emit("new FormData()")>]
    /// Creates a new FormData object
    let create() : FormData = jsNative

Should this maybe be moved into fable-browser so that this functionality is available for plain fable projects without an external dependency or the need to declare this yourself?

What namespace to open?

It's really hard to find the information what namespace or module to open.

I've added nuget package Fable.Browser.Dom, but can't open anything.

image

Could someone please add at least a single line into README to explain what goes where ...

Update to `Fable.Browser.Url 1.3` causes compilation error

Hi,

After an update of Fable.Browser.Url from 1.2 --> 1.3 I've started to receive an error:

FSC: Error FS0193 : The module/namespace 'Types' from compilation unit 'Browser.Url' did not contain the val 'ValLinkagePartialKey(Create)'

Do you have any idea what can cause a problem? I assume that this can be somehow correlated to this PR: #115

Dom API Create throws "Illegal constructor"

Calling HTMLImageElement.Create (512., 512.) throws "Uncaught TypeError: Illegal constructor".

I came across the same issue as #25 but the fix for that didn't work.
I was going to just submit a PR with the fix @alfonsogarciacaro proposed because I can confirm that changing

[<Emit("new $0($1...)">]

to

[<Emit("new Image($1...)")>]

works.

However I noticed that this pattern is used throughout Browser.Dom.fs so I tried ___.Create for a few other elements types and it looks like they all have the same issue (atleast all the ones I tested).
It's not like it's just a few types that weren't initially tested and happen to have quirks; has something changed about the way fable handles type names or something?

Move adoptedStyleSheets from Element to Node, also add getRootNode()?

I think there's an argument for moving adoptedStyleSheets from Element to Node. According to the spec and examples, you only expect to see this on a root node such as HTMLDocument and ShadowRoot.

Neither of these appears to be an Element, but both inherit from Node:

https://developer.mozilla.org/en-US/docs/Web/API/HTMLDocument

image

and

https://dom.spec.whatwg.org/#documentfragment

In addition, it would be useful to add getRootNode() with the same extension (or elsewhere).

https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode

If in agreement, I can submit a PR that changes this code to

type Node with 
    /// returns this DocumentOrShadow adopted stylesheets or sets them.
    /// https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets
    [<Emit("$0.adoptedStyleSheets{{=$1}}")>]
    member __.adoptedStyleSheets with get(): CSSStyleSheet array = jsNative and set(v: CSSStyleSheet array) = jsNative
   [<Emit("$0.getRootNode()")>]
    member __.getRootNode() : Node = jsNative    

Information about method extensions

I am using/testing Fable.Browser.Css in one of my projects and discover something.

In order to get the method extensions working, I need to manually open the module Browser.CssExtensions

Otherwise, the extensions are not working.

Browser.Dom.document.styleSheets // Error

open Browser.CssExtensions

Browser.Dom.document.styleSheets // Ok

So should we remove [<AutoOpen>] so people know don't expect it to be working out of the box?

I suspect it will be the same for all the other method extension.

PS: I think AutoOpen needs you to open part of the namespace in order to work.

WebStorage API should use `DOMString`

According to MDN the WebStorage API works with DOMString.

The API contained under Fable.Browser.WebStorage use sometimes obj or string.

Using string is less problematic however using obj leads to some unexpected behaviour.

    let isActive =
        let storageValue = WebStorage.localStorage.getItem("admin_mode") // This is an obj 
        if isNull storageValue then
            false // This returns a bool
        else
            storageValue :?> bool // This returns a string at runtime which then lead to subtle bugs

Is there any reason to not binding to DOMString?

encodeURIComponent

Not sure why but I can't see window.encodeURIComponent. I see it in the source code Browser.Dom.fs but not available in IntelliSense

missing types MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback

references fable-compiler/ts2fable#290


babylonjs contains this:

interface Navigator {
    mozGetVRDevices: (any: any) => any;
    webkitGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
    mozGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
    msGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
    webkitGetGamepads(): Gamepad[];
    msGetGamepads(): Gamepad[];
    webkitGamepads(): Gamepad[];
}

That causes an error:

grafik

If I F12 on MediaStreamConstraints in Visual Studio in the babylon.d.ts file, I go to C:\Program Files (x86)\Microsoft SDKs\TypeScript\2.8\lib.dom.d.ts.

So I think these types need to be added to Fable.Import.Browser.


Note: I'm not sure if this is even the right repository.

Intellisense shows there is apparently already a type MediaStream, but I can't find that anywhere?
grafik

KeyboardEvent.keyCode is being deprecated, need to implement KeyboardEvent.code instead

From MDN:

The deprecated KeyboardEvent.keyCode read-only property represents a system and implementation dependent numerical code identifying the unmodified value of the pressed key. This is usually the decimal ASCII (RFC 20) or Windows 1252 code corresponding to the key. If the key can't be identified, this value is 0.

You should avoid using this if possible; it's been deprecated for some time. Instead, you should use KeyboardEvent.code, if it's implemented. Unfortunately, some browsers still don't have it, so you'll have to be careful to make sure you use one which is supported on all target browsers.

uint64 properties in MediaRecorderOptions not working with Fable 4

let o = createEmpty<MediaRecorderOptions>
o.audioBitsPerSecond <- 48_000UL
o.mimeType <- mimeType
let recorder = MediaRecorder.Create (stream, o)

This used to work for me in the past (pre Fable 4). However, now I'm getting TypeError: Cannot convert a BigInt value to a number on the last line. If I do !!48_000, the snippet works fine.

I wonder whether the properties in MediaRecorderOptions and MediaRecorder (and possibly elsewhere) shouldn't be changed to simple int. These properties don't need the int64 range, and the unsigned restriction feels merely cosmetic in any Fable code. It would be a breaking change, albeit on a less common API, but better that than unexpected runtime failures.

Clipboard API event handler argument types are incorrect

Dear Fable team,

I'm fairly new to Fable, just trying it out, but while experimenting with it I encountered a problem in the clipboard API (the old one, not Navigator based) : the argument types of the event handlers were for DragEvent but the MDN docs suggested ClipboardEvent should be expected.

I created a PR (#55 ) with a suggested solution.

Best Regards,
@kodfodrasz

Missing Element.closest(selector)

Element is missing closest(selector) member.

MDN documentation

I propose to add it with the form:

 abstract closest: selectors : string -> Element option
 abstract closest: element : Element -> Element option

Element option inform the user that this function can return null

DataTransfer properties are not settable

DataTransfer property getters are there, but are missing setters:

type [<AllowNullLiteral>] DataTransfer =
abstract dropEffect: string
abstract effectAllowed: string
abstract files: FileList
abstract items: DataTransferItemList
abstract types: DOMStringList
abstract clearData: ?format: string -> bool
abstract getData: format: string -> string
abstract setData: format: string * data: string -> bool

The deprecated Fable.Import has them:
https://github.com/fable-compiler/fable-import/blob/master/Browser/Fable.Import.Browser.fs#L1553-L1561

Add ScrollToOptions Support

Would you accept a PR to add ScrollToOptions support for window here:

abstract scroll: ?x: float * ?y: float -> unit

Something like:

[<StringEnum>]
type ScrollBehaviour =
    | Auto
    | Smooth

type ScrollToOptions =
    { top : float
      left : float
      behavior: ScrollBehaviour }

type Window =
    (*old code as before *)
    ...
    abstract scroll: ?x: float * ?y: float -> unit
    abstract scrollBy: ?x: float * ?y: float -> unit
    abstract scrollTo: ?x: float * ?y: float -> unit
    (* new code *)
    abstract scroll : ScrollToOptions -> unit
    abstract scrollBy : ScrollToOptions -> unit
    abstract scrollTo : ScrollToOptions -> unit

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.